在Clojure中,
(def x 3)
(eval '(prn x))
打印3,而
(let [y 3]
(eval '(prn y)))
和
(binding [z 3] (eval '(prn z)))
生成'无法解析var'异常。
根据http://clojure.org/evaluation,eval
,load-string
等生成临时命名空间以评估其内容。因此,我希望上述代码示例都不起作用,因为(def x 3)
是在我当前的命名空间中完成的,而不是eval
创建的。{/ p>
eval
使用绑定变量的表单而不使用def
?谢谢!
答案 0 :(得分:15)
1:
这不起作用的原因是(或多或少)在您链接的页面上给出:
It is an error if there is no global var named by the symbol […]
和
[...]
在当前命名空间中完成查找以查看是否存在映射 从符号到变量。如果是这样的话 value是绑定的值 由符号引用的var。
- 醇>
这是一个错误。
eval
评估空(CL-lingo中的null)词汇环境中的表单。这意味着,您无法从调用者的作用域访问词法变量绑定。此外,binding
为现有变量创建新的绑定,这就是为什么你不能“单独”使用它,而没有declare
d或def
你尝试绑定的变量。此外,词汇变量(至少在CL中,但如果Clojure不是这样,我会感到惊讶)已经在运行时停止存在 - 它们被转换为地址或值。
有关此主题,请参阅我的older post。
2:
因此,您必须使用动态变量。您可以避免显式def
,但您仍然至少需要declare
它们(def
的var名称没有绑定):
user=> (declare ^:dynamic x)
#'user/x
user=> (binding [x 10] (eval '(prn x)))
10
nil
顺便说一句:我想你知道为什么你需要eval,并且当其他解决方案合适时,它的使用是considered evil。