对clojure的新手,尝试编译以下代码,用于布尔表达式求值程序
;core.clj
(ns my-app.core
(:gen-class))
(defn t [& args] (if (empty? args) t
((first args) t (first (rest args)))))
(defn f [& args] (if (empty? args) f
((first args) f (first (rest args)))))
(defn | [cond1 cond2] (if (= cond1 t) t
(if (= cond2 t) t f)))
(defn & [cond1 cond2] (if (= cond1 f) f
(if (= cond2 f) f t)))
(defn ! [& args] (if (= (first args) t)
(apply f (rest args))
(if ( = (first args) f)
(apply t (rest args))
(! (apply (first args) (rest args))))))
(defn -main [& args]
(loop [line (read-line)]
(do
(println (eval (read-string (apply str "" (interpose \space (seq (str "(" line ")")))))))
(if (= (count line) 1) nil (recur (read-line))))))
每次我做“lein run”并输入字符串“(t | t)= t”我收到以下错误
Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: t in this context
但是如果我在“src / my_app /”目录中打开一个新的nrepl,并输入命令
(-main)
我得到正确的字符串和结果
( ( t | t ) = t )
true
我应该注意,在运行lein run
时其他字符串字符串“+ 1 2 3 4 5 6”将正确评估,但由于某种原因,它将无法识别该函数(t ...)
有人知道发生了什么事吗?
答案 0 :(得分:3)
eval
使用*ns*
的当前(线程绑定)值来确定您当前“in”的命名空间,该命名空间控制如何解析不合格的符号。在运行(ns my-app.core ...)
后的repl中,您位于my-app.core
命名空间中,因此eval会找到您在那里定义的t
。但是在编译之后,即使您仍然在t
中定义了my-app.core
,当您的程序开始运行时,您在user
命名空间中并且eval无法找到t
。
所以您需要做的就是使用-main
将my-app.core
中的命名空间更改为binding
:
(defn -main [& args] (binding [*ns* (the-ns 'my-app.core)] (loop [line (read-line)] (println (eval (read-string (apply str (interpose \space (str "(" line ")")))))) (when-not (= (count line) 1) (recur (read-line))))))