【问题标题】:How to use command line arguments in Clojure?如何在 Clojure 中使用命令行参数?
【发布时间】:2018-10-08 20:00:08
【问题描述】:

我正在完成我的第一个 Clojure 程序之一。我剩下要做的一件事是让我的程序接受命令行参数。 args 的数量可以变化(但至少需要一个),然后每个命令行 arg 需要作为参数提供给我的 main 中的函数,一次一个。我一直在网上阅读,似乎clojure/tools.cli 是这样做的方法,(也许使用parse-opts?)。但我无法为我的一生弄清楚。没有验证,这确实需要发生——用户提供的任何内容都是有效的。 (唯一需要检查的是至少提供了一个参数)。有什么建议可以解决这个问题吗?

我遇到的所有例子看起来都很复杂,很容易让我头疼。

我正在尝试做的一个简单示例是在用户提供任意数量的命令行参数之后,然后让 clojure 在终端的新行中​​打印每个字符串。

我使用 leiningen 来运行我的程序。

【问题讨论】:

  • 您能否展示您使用clojure.tools.cli/parse-opts 的尝试——即。你有什么代码,你想要什么行为,你实际上得到了什么行为? (请参阅帮助中心的 minimal reproducible example 页面,了解如何将最短的代码示例组合在一起,让其他人自己看到您的问题)。
  • ...实际上,如果 everything 是有效的,你可以说不需要 parse-opts,只需实现一个对其参数列表进行操作的 main 函数。

标签: clojure leiningen


【解决方案1】:

简单的方法是使用clojure.core/*command-line-args*:

(doseq [arg *command-line-args*]
  (println (str "Read an argument: " arg)))

【讨论】:

    【解决方案2】:

    因为您的整个问题似乎可以归结为:

    我正在尝试做的一个简单示例是在用户提供任意数量的命令行参数之后,然后让 clojure 在终端的新行中​​打印每个字符串。

    我会回答的。这可以相当简洁地完成:

    (defn -main [& args] ; & creates a list of var-args
      (if (seq args)
        ; Foreach arg, print the arg...
        (doseq [arg args]
          (println arg))
    
        ; Handle failure however here
        (throw (Exception. "Must have at least one argument!"))))
    

    注意,除非您绝对希望在传递 0 个参数时彻底失败,否则您可以跳过 seq 检查。如果args 为空,doseq 将不会运行,因为没有任何东西可以迭代。

    您还可以将整个 doseq 替换为:

    (mapv println args)
    

    但这可以说是对mapv的滥用。

    【讨论】:

    • 太棒了,非常感谢!从您的示例中,我已经能够将其写下来: ))) `
    • @orangeorangepeel 你可能不想给(find-files arg paths) 打两次电话。听起来很贵。您应该调用一次,使用 let 绑定保存结果,然后改用它。
    • 这正是我在让它正常工作后最终做的事情——再次感谢! :)
    • (if-not (empty? args)...) 可以缩短为 (if (seq args)...)
    • @Sonicsmooth 是的,我最近才采用seq 成语。在我开始正确使用nil 之前,我总是觉得很尴尬。回家后我会尽量记住更新。
    【解决方案3】:

    Clojure Spec 可以做很多事情,解析和验证命令行参数就是其中之一。这是一个例子:

    (ns cmdargs.core
      (:require [clojure.spec.alpha :as spec]))
    
    ;; Specification of a single argument.
    ;; For example, replace `any?` by `number?`
    ;; if your program only accepts numeric args.
    (spec/def ::arg any?)
    
    (spec/def ::args (spec/+ ::arg))
    
    (defn my-fun [& args]
      (doseq [arg args]
        (println "Got arg: " arg)))
    
    (defn -main [& args]
      (let [parsed-args (spec/conform ::args args)]
        (if (= ::spec/invalid parsed-args)
          (do (println "Bad commandline arguments")
              (spec/explain ::args args))
          (apply my-fun parsed-args))))
    

    Clojure Spec 从 Clojure 1.9 版开始提供。

    【讨论】:

      猜你喜欢
      • 2013-01-13
      • 2021-08-21
      • 2012-11-30
      • 2013-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-03
      • 2014-06-01
      相关资源
      最近更新 更多