Clojure 中的变量范围 + eval [英] Variable scope + eval in Clojure

查看:18
本文介绍了Clojure 中的变量范围 + eval的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Clojure 中,

In Clojure,

(def x 3)
(eval '(prn x))

打印 3,而

(let [y 3]
   (eval '(prn y)))

(binding [z 3] (eval '(prn z)))

生成无法解析 var"异常.

generate an 'Unable to resolve var' exception.

根据http://clojure.org/evaluationevalload-string 等生成临时命名空间来评估它们的内容.因此,我不希望上述代码示例都起作用,因为 (def x 3) 是在我当前的命名空间中完成的,而不是由 eval 创建的.

According to http://clojure.org/evaluation, eval, load-string, etc generate temporary namespaces to evaluate their contents. Therefore, I'd expect neither of the above code samples to work, since (def x 3) is done in my current namespace, not the one created by eval.

  1. 为什么第一个代码示例有效而不是后两个?
  2. 如何在不使用def的情况下eval一个带有绑定变量的表单?
  1. Why does the first code sample work and not the last two?
  2. How can I eval a form with bound variables without using def?

谢谢!

推荐答案

1.:

这不起作用的原因是(或多或少)在您链接的页面上给出:

The reason this doesn't work is (more or less) given on the page you linked:

It is an error if there is no global var named by the symbol […]

还有:

[…]

  1. 在当前命名空间中进行查找,看是否有映射从符号到变量.如果是这样,则value 是绑定的值符号引用的 var.

  1. A lookup is done in the current namespace to see if there is a mapping from the symbol to a var. If so, the value is the value of the binding of the var referred-to by the symbol.

这是一个错误.

eval 评估空表单 (null in CL-lingo) 词法环境.这意味着,您无法从调用者的范围访问词法变量绑定.此外,binding 为现有的变量创建新的绑定,这就是为什么你不能单独"使用它,而没有 declared 或 defed您尝试绑定的变量.此外,词法变量(至少在 CL 中,但如果 Clojure 不是这种情况,我会感到惊讶)在运行时已经不复存在——它们被转换为地址或值.

eval evaluates forms in an empty (null in CL-lingo) lexical environment. This means, that you cannot access lexical variable bindings from the caller's scope. Also, binding creates new bindings for existing vars, which is why you cannot use it "by itself", without having declared or defed the variables you try to bind. Besides, lexical variables (at least in CL, but I would be surprised if this wasn't the case for Clojure) already ceased to exist at runtime – They are translated to addresses or values.

另见我关于此的旧帖子主题.

2.:

所以,你必须使用动态变量.你可以避免显式的 def,但你至少仍然需要 declare 它们(其中 def 的 var 名称没有绑定):

So, you have to use dynamic variables. You can avoid the explicit def, but you still at least need to declare them (which defs var names without bindings):

user=> (declare ^:dynamic x)
#'user/x
user=> (binding [x 10] (eval '(prn x)))
10
nil

顺便说一句:我想您知道为什么需要 eval,并且它的用途是 考虑过邪恶当其他解决方案合适时.

By the way: I suppose you know why you need eval, and that its use is considered evil when other solutions would be appropriate.

这篇关于Clojure 中的变量范围 + eval的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆