Clojure:在脚本中使用*命令行args*而不是REPL
我在Eclipse中运行clojure。我想在运行clojure时将参数传递给它。在下面的示例中,参数在REPL中可用,但在脚本本身中不可用。我需要做什么才能在下面的示例中,在REPL中键入arg1返回第一个参数 脚本:Clojure:在脚本中使用*命令行args*而不是REPL,clojure,Clojure,我在Eclipse中运行clojure。我想在运行clojure时将参数传递给它。在下面的示例中,参数在REPL中可用,但在脚本本身中不可用。我需要做什么才能在下面的示例中,在REPL中键入arg1返回第一个参数 脚本: (NS Test) (def arg1 (nth *command-line-args* 0)) 在点击Eclipse“运行”之后 Clojure 1.1.0 1:1用户=># 1:2测试=>arg1 无 1:3测试=>*命令行参数* (“鸟”“狗”“猫”“猪”) 1:4测试
(NS Test)
(def arg1 (nth *command-line-args* 0))
在点击Eclipse“运行”之后
Clojure 1.1.0
1:1用户=>#
1:2测试=>arg1
无
1:3测试=>*命令行参数*
(“鸟”“狗”“猫”“猪”)
1:4测试=>(def arg2(第n个*命令行args*1))
#'测试/arg2
1:5测试=>arg2
“狗”
1:6测试=>
似乎在*命令行args*
获取值之前,您的arg1
就已经定义好了*命令行args*
位于clojure.core
中,因此每个名称空间都应该能够看到它(除非您定义名称空间并明确告诉它排除core
或排除该变量)。我不知道Eclipse如何启动REPL,也不知道它如何/何时加载名称空间或用户代码,所以我不知道问题出在哪里
但是您可以将arg1
转换为一个函数,然后它应该始终返回*命令行args*
的当前值(因为它将在运行时解析,*命令行args*
在您调用该函数时应该有一个值)
更好的方法是,如果(n*命令行args*0)
真的有那么多需要键入的内容(我真的不这么认为),您可以编写一个更好的函数:
(defn ARGV [n] (nth *command-line-args* n))
然后使用(ARGV 0)
,(ARGV 1)
等。请记住,向量本身就是其参数的函数,因此您可以同样轻松地直接执行(*命令行args*n)
(一旦您确定*命令行args*
不是nil
,否则您将得到NullPointerException。)
在Clojure中,使用大量的def
s为顶级事物指定名称通常不惯用。如果您想在本地引用命令行参数,并在一段时间内给它们取一个较短的名称,那么有let
:
(defn foo []
(let [arg1 (nth *command-line-args* 0)]
...))
同样,这种方式
arg1
应该在运行时获得它的值(无论何时调用foo
),因此它应该可以工作。Brian,感谢您的建议。这显然与Eclipse中REPL的启动方式有关;直接运行脚本可以按预期工作。仅供参考,不确定原因,但将arg1定义为函数的设置并不像我预期的那样有效。下面是一个新脚本和直接运行它的输出。(ns测试)(println命令行args)(defn arg1[](第n个命令行args 0))并运行它。。。java-cp/Path_to_jar/clojure.jar clojure.main.com.clj猫狗(猫狗)#(println arg1)
(defn ARGV [n] (nth *command-line-args* n))
(defn foo []
(let [arg1 (nth *command-line-args* 0)]
...))