lein run,不会正常运行,虽然干净的nrepl会

时间:2013-03-26 08:45:32

标签: clojure leiningen

对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 ...)

有人知道发生了什么事吗?

1 个答案:

答案 0 :(得分:3)

eval使用*ns*的当前(线程绑定)值来确定您当前“in”的命名空间,该命名空间控制如何解析不合格的符号。在运行(ns my-app.core ...)后的repl中,您位于my-app.core命名空间中,因此eval会找到您在那里定义的t。但是在编译之后,即使您仍然在t中定义了my-app.core,当您的程序开始运行时,您在user命名空间中并且eval无法找到t

所以您需要做的就是使用-mainmy-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))))))