2013-03-26 33 views
1

新來的Clojure,試圖編譯下面的代碼,對於布爾表達式求值雷音運行,將無法正確運行 - 主,雖然乾淨nrepl將

;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)))))) 

每次我做「雷音運行」輸入字符串「(T | T)= T」我收到以下錯誤

Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: t in this context 

但是如果我打開了在「源/程序my_app /」目錄新nrepl,並輸入命令

(-main) 

我得到正確的字符串,並導致

((t | t) = t) 
true 

我應該注意,運行雷音運行

其他弦弦而「+ 1 2 3 4 5 6」將正確評估,但由於某種原因它不會識別該功能(t ...)

任何人有什麼想法是怎麼回事?

回答

3

eval使用當前(線程綁定)值*ns*來確定當前「in」中的哪個名稱空間,該名稱空間控制着如何解析非限定符號。在運行(ns my-app.core ...)後的repl處,您處於my-app.core名稱空間中,因此eval會找到您在此處定義的t。但是,編譯完成後,即使您仍然在my-app.core中定義了t,當程序開始運行時,您將位於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)))))) 
+0

謝謝你,是完全固定的一切。 – 2013-03-26 19:23:12