Binding 可变范围+;在Clojure中评估

Binding 可变范围+;在Clojure中评估,binding,clojure,eval,let,Binding,Clojure,Eval,Let,在Clojure (def x 3) (eval '(prn x)) 打印3份,而 (let [y 3] (eval '(prn y))) 及 生成“无法解析变量”异常 根据,eval,load string等生成临时名称空间以评估其内容。因此,我希望上述两个代码示例都不起作用,因为(def x 3)是在我当前的名称空间中完成的,而不是由eval创建的名称空间 为什么第一个代码示例有效,而最后两个不起作用 如果不使用def,如何eval带有绑定变量的表单 谢谢 1: 这不起作用的原因(

在Clojure

(def x 3)
(eval '(prn x))
打印3份,而

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

生成“无法解析变量”异常

根据,
eval
load string
等生成临时名称空间以评估其内容。因此,我希望上述两个代码示例都不起作用,因为
(def x 3)
是在我当前的名称空间中完成的,而不是由
eval
创建的名称空间

  • 为什么第一个代码示例有效,而最后两个不起作用
  • 如果不使用
    def
    ,如何
    eval
    带有绑定变量的表单
  • 谢谢

    1:

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

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

    [……]

  • 在当前命名空间中执行查找,以查看是否存在映射 从符号到变量。如果是,则 value是的绑定的值 符号所指的变量

  • 这是一个错误

  • eval
    在空(用CL术语)词汇环境中计算表单。这意味着您无法从调用者的作用域访问词法变量绑定。另外,
    binding
    为现有变量创建新的绑定,这就是为什么在没有
    声明
    d或
    def
    ed尝试绑定的变量的情况下,不能“单独”使用它的原因。此外,词汇变量(至少在CL中,但如果Clojure不是这样的话,我会感到惊讶)在运行时已经不存在了——它们被转换为地址或值

    另请参见我关于此主题的介绍

    2.:

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


    顺便说一句:我想您知道为什么需要eval,它的使用是在其他解决方案合适的时候。

    请注意,这在Clojure 1.3中不起作用。您必须使用
    (declare^:dynamic x)
    。谢谢!我现在明白我的问题了——我假设“null lexical scope”也指“null名称空间”,但快速测试表明
    eval
    在当前名称空间中工作,这就是为什么它可以访问名称空间变量,但不能访问词法变量。回答得很好,你的链接也很有帮助!不客气!我很高兴这有帮助。另外,感谢您的接受。我想您应该引用内部(prnx)。我在尝试编写一个宏时遇到了这个问题,该宏将自动执行类似于
    (let[x41,y(incx)]{:xx,:yy})
    (显然只对大型let块和大量复杂的数学感兴趣)。我尝试了
    (defmacro hashup[vars]`(apply hash map(map-vector(map-keyword~vars)(map-eval~vars)))
    (只有一个backtick)并在这里遇到了问题。我看不出有什么办法可以使let块变干:(
    It is an error if there is no global var named by the symbol […]
    
    user=> (declare ^:dynamic x)
    #'user/x
    user=> (binding [x 10] (eval '(prn x)))
    10
    nil