Clojure谜语:eval,宏和命名空间

时间:2012-02-07 12:51:25

标签: macros 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的澄清

1 个答案:

答案 0 :(得分:4)

(println (hello))(println (my-eval "(hello)"))是完全相同的陈述 - 唯一的区别是会让您的编辑更加困惑。 my-eval与真实eval无法比较。区别在于my-eval的参数在编译时需要是一个字符串 - 以下错误因为符号x无法转换为字符串。

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

这使得my-eval毫无意义 - 您可以“评估”文字字符串,或者您可以删除引号和my-eval并具有相同功能的代码(您的编辑将会理解)。

另一方面,

Real eval尝试在运行时编译代码。在这里,它失败了,因为它是从main命名空间而不是hello命名空间运行的,正如@Matthias Benkard指出的那样。