Leiningen 命令参数解析
Leiningen command args parsing
我是 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
当我 运行 -main 来自 REPL 时,它运行良好。当我在 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>
terminal/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
:keys
解构仅适用于关键字,而您认为通过 -main
进入的关键字实际上不是关键字而是字符串,每个字符串都以冒号开头。要确认这一点,请对传入的参数使用函数 type
。
来自 https://clojure.org/guides/destructuring 我找到了这句话:
The :keys key is for associative values with keyword keys
如果您确实需要将传入参数转换为关键字,请使用 keyword
:
(keyword (subs ":f" 1))
所以在你的情况下你可以这样做:
(map (comp keyword #(subs % 1)) [":f" ":w" ":h"])
,但是 [":f" ":w" ":h"]
你会得到 args
.
当然,如果您决定省略冒号,事情会变得简单一些,这在 Clojure 之外没有意义 reader:https://clojure.org/reference/reader.
谢谢! REPL 和 Lein 对 'args' 的不同解释有点令人困惑。
REPL 在
中解释 ':param1'
-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)))
我是 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
当我 运行 -main 来自 REPL 时,它运行良好。当我在 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>
terminal/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
:keys
解构仅适用于关键字,而您认为通过 -main
进入的关键字实际上不是关键字而是字符串,每个字符串都以冒号开头。要确认这一点,请对传入的参数使用函数 type
。
来自 https://clojure.org/guides/destructuring 我找到了这句话:
The :keys key is for associative values with keyword keys
如果您确实需要将传入参数转换为关键字,请使用 keyword
:
(keyword (subs ":f" 1))
所以在你的情况下你可以这样做:
(map (comp keyword #(subs % 1)) [":f" ":w" ":h"])
,但是 [":f" ":w" ":h"]
你会得到 args
.
当然,如果您决定省略冒号,事情会变得简单一些,这在 Clojure 之外没有意义 reader:https://clojure.org/reference/reader.
谢谢! REPL 和 Lein 对 'args' 的不同解释有点令人困惑。
REPL 在
中解释 ':param1'-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)))