Macros Clojure riddle:eval、宏和名称空间

Macros Clojure riddle:eval、宏和名称空间,macros,clojure,eval,Macros,Clojure,Eval,在clojure中,宏赋予程序员巨大的能力评估也非常强大。两者之间存在一些细微的差别。我希望这个谜语能对这个话题有所启发 (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)"))))

在clojure中,宏赋予程序员巨大的能力<代码>评估也非常强大。两者之间存在一些细微的差别。我希望这个谜语能对这个话题有所启发

(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条语句中,哪一条会导致异常,为什么其他语句不会

在对这个美丽的问题进行调查之后,我得出了下面的谜语。感谢@Matthias Benkard的澄清

(println(hello))
(println(my eval)(hello)”)
是完全相同的语句——唯一的区别是会让编辑更加困惑<代码>我的评估与真实的
评估
不可比。不同之处在于
my eval
的参数在编译时需要是一个字符串——下面的错误是因为符号
x
不能转换为字符串

(def x "(hello)")
(my-eval x)
这使得
my eval
毫无意义-您可以“eval”一个文本字符串,也可以删除引号和
my eval
,并具有相同的功能代码(您的编辑器将理解)

另一方面,Real
eval
,尝试在运行时编译代码。在这里,它失败了,因为它是从
main
名称空间运行的,而不是@Matthias Benkard指出的
hello
名称空间。

(println(hello))
(println(my eval)(hello)”)
是完全相同的语句,唯一的区别是它们会让编辑器更加困惑<代码>我的评估与真实的
评估
不可比。不同之处在于
my eval
的参数在编译时需要是一个字符串——下面的错误是因为符号
x
不能转换为字符串

(def x "(hello)")
(my-eval x)
这使得
my eval
毫无意义-您可以“eval”一个文本字符串,也可以删除引号和
my eval
,并具有相同的功能代码(您的编辑器将理解)

另一方面,Real
eval
,尝试在运行时编译代码。在这里,它失败了,因为它是从
main
名称空间运行的,而不是@Matthias Benkard指出的
hello
名称空间