2012-02-07 54 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