2012-02-07 50 views
1

在clojure中,宏爲程序員提供了巨大的力量。 eval也是非常強大的。兩者之間存在一些細微的差異。我希望這個謎題能對這個話題有所啓發。Clojure謎題:eval,宏和命名空間

(ns hello) 
(defmacro my-eval [x] `~(read-string x)) 
(defn hello[] "Hello") 
(defn run-stuff [] 
    (println (hello)) 
    (println (my-eval "(hello)")) 
    (println (eval (read-string "(hello)")))) 
(ns main) 
(try (hello/run-stuff) 
    (catch Exception e (println e))) 

在裏面run-stuff體的3個語句,其中一個導致異常,爲什麼其他的人不?

在調查這個美麗的問題Clojure - (read-string String calling function後,我制定了以下謎語。感謝@Matthias Benkard的澄清

回答

4

(println (hello))(println (my-eval "(hello)"))是完全相同的陳述 - 唯一的區別是你會更加困惑你的編輯器。 my-eval與實際eval不具有可比性。不同之處在於my-eval的參數在編譯時需要是一個字符串 - 以下錯誤由於符號x不能被轉換爲字符串。

(def x "(hello)") 
(my-eval x) 

這使得my-eval毫無意義的 - 你可以「EVAL」一個字符串,也可以刪除引號和my-eval,並具有同樣功能的代碼(即你的編輯就會明白)。

另一方面,實際eval試圖在運行時編譯代碼。正如@Matthias Benkard指出的那樣,它的失敗是因爲它是從main命名空間運行的,而不是命名空間hello