在 Clojure 中,
(def x 3)
(eval '(prn x))
打印 3,而
(let [y 3]
(eval '(prn y)))
and
(binding [z 3] (eval '(prn z)))
生成“无法解析 var”异常。
根据http://clojure.org/evaluation http://clojure.org/evaluation, eval
, load-string
等生成临时名称空间来评估其内容。因此,我希望上述代码示例都不起作用,因为(def x 3)
是在我当前的命名空间中完成的,而不是由eval
.
- 为什么第一个代码示例可以工作,而后两个则不行?
- 我怎么能够
eval
具有绑定变量而不使用的形式def
?
Thanks!
1.:
这不起作用的原因(或多或少)在您链接的页面上给出:
It is an error if there is no global var named by the symbol […]
And:
[…]
在当前命名空间中进行查找以查看是否存在映射
从符号到变量。如果是这样,则
value 是绑定的值
符号引用的 var。
这是一个错误。
eval
评估空(null http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/glo_n.html#null_lexical_environment在 CL-lingo 中)词汇环境。这意味着您无法从调用者的范围访问词法变量绑定。还,binding
为现有变量创建新的绑定,这就是为什么你不能“单独”使用它,而不需要declare
d or def
编辑您尝试绑定的变量。此外,词法变量(至少在 CL 中,但如果 Clojure 不是这种情况,我会感到惊讶)在运行时已经不再存在——它们被转换为地址或值。
另请参阅我的较旧的帖子 https://stackoverflow.com/questions/2575262/executing-a-dynamically-bound-function-in-clojure/2575425#2575425关于这个话题。
2.:
所以,你必须使用动态变量。你可以避免显式的def
,但你至少还需要declare
他们(其中def
不带绑定的 var 名称):
user=> (declare ^:dynamic x)
#'user/x
user=> (binding [x 10] (eval '(prn x)))
10
nil
顺便说一句:我想你知道为什么需要 eval,并且它的用途是被认为是邪恶的 https://stackoverflow.com/questions/2571401/why-exactly-is-eval-evil当其他解决方案合适时。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)