【问题标题】:Leiningen command args parsingLeiningen 命令参数解析
【发布时间】:2017-10-12 21:03:26
【问题描述】:

我是 Clojure 的新手,我对 leib 命令行参数有疑问,我无法解决。我的应用很简单:

 (defn -main
  [& args]
  (println (apply hash-map args))
  (let [{:keys [f w h]} (apply hash-map args)]
    (println f w h)
;     (init-frame w h)
;     (draw-values f w h)
))

终端输出:

lein run :f bit-xor :w 200 :h 200
{:w 200, :h 200, :f bit-xor}
nil nil nil

当我从 REPL 运行 -main 时,它运行良好。当我在 core.clj 中定义一个 hashmap 时,这样的效果也很好。

(def my-args (hasmap :f "bit-xor" :w 200 :h 200))

我不明白,为什么我的 'f'、'w' 和 'h' 在 let get nil 中。有人可以帮忙吗?

我做了一个特殊的小应用程序只是为了测试。

 (ns cmdargs.core
 (:gen-class))

(defn -main
 [& args]
 (println "args: " args)
 (println "args map: " (apply hash-map args))
 (println "param keys: " (keys (apply hash-map args)))
 (println "param vals: " (vals (apply hash-map args)))
 (let [{:keys [param1 param2]} (apply hash-map args)]
   (println "param1: " param1)
   (println "param2: " param2)))

REPL 输出:

 cmdargs.core> (-main :param1 200 :param2 300)
 args:  (:param1 200 :param2 300)
 args map:  {:param2 300, :param1 200}
 param keys:  (:param2 :param1)
 param vals:  (300 200)
 param1:  200
 param2:  300
 nil
 cmdargs.core>

终端/lein 输出:

 cmdargs$ lein run :param1 200 :param2 300
 Java HotSpot(TM) Client VM warning: TieredCompilation is disabled in this release.
 Java HotSpot(TM) Client VM warning: TieredCompilation is disabled in this release.
 args:  (:param1 200 :param2 300)
 args map:  {:param1 200, :param2 300}
 param keys:  (:param1 :param2)
 param vals:  (200 300)
 param1:  nil
 param2:  nil

【问题讨论】:

  • 这是一个错字(defn my-args ...)?它应该是def
  • 谢谢@Shlomi!我纠正了。但是 (def my-args ...) 只是为了检查 'let' 中的解构工作而定义的。

标签: clojure leiningen


【解决方案1】:

:keys 解构只适用于关键字,而您认为通过-main 进入的关键字实际上不是关键字而是字符串,每个字符串都以冒号开头。要确认这一点,请在传入的参数上使用函数type

来自https://clojure.org/guides/destructuring 我找到了这句话:

:keys 键用于与关键字键关联的值

如果您确实需要将传入的参数转换为关键字,请使用keyword:

(keyword (subs ":f" 1))

所以在你的情况下,你可以这样做:

(map (comp keyword #(subs % 1)) [":f" ":w" ":h"])

,但您将使用 args 代替 [":f" ":w" ":h"]

当然,如果您决定省略冒号,事情会变得更简单一些,这在 Clojure 阅读器之外没有意义:https://clojure.org/reference/reader

【讨论】:

  • 谢谢! REPL 和 Lein 对“args”的解释不同,这有点令人困惑。
  • 是的。我想当我们在 REPL 时,我们在 Clojure Reader 中。另一方面,命令行 args 只能以字符串的形式通过也就不足为奇了。
【解决方案2】:

谢谢! REPL 和 Lein 对“args”的解释不同,这有点令人困惑。

REPL 解释 ':param1' in

-main :param1 200

进入clojure.lang.Keyword

但在莱因

lein run :param1 200

进入'java.lang.String'

我之前尝试过 :strs 而不是 :keys 但忘记了冒号。这是有效的:

(defn -main
 [& args]
 (let [{:strs [:param1 :param2]} (apply hash-map args)]
 (println "param1: " param1)
 (println "param2: " param2)))

当然,在这种情况下,参数名称前的冒号没有任何意义。

对于 :keys 我做了以下操作

(defn -main
  [& args]

  (let [{:keys [param1 param2]} 
     (into {} (for [[k  v] (apply hash-map args)]
                   [(keyword (apply str (rest k))) v]))]
  (println "param1: " param1)
  (println "param2: " param2)))

【讨论】:

  • Lein 在这里并不是一个真正的大玩家 - 它与在命令行上调用 java 没有什么不同。
  • 没有。你是对的'lang'是小'l'而不是'L'。 java.lang.String 和 cojure.lang.Keyword 是正确的。
猜你喜欢
  • 2011-06-01
  • 2013-03-21
  • 2012-01-26
  • 2011-08-15
  • 1970-01-01
相关资源
最近更新 更多