Clojure 为什么defn似乎在函数体中计算(def符号)?
在玩弄Clojure时,我编写了一个函数,该函数依赖于在第一次运行时未定义someSymbol,因为resolve someSymbol将返回nil。事实证明,通过定义函数中某处的def,可以定义符号:Clojure 为什么defn似乎在函数体中计算(def符号)?,clojure,Clojure,在玩弄Clojure时,我编写了一个函数,该函数依赖于在第一次运行时未定义someSymbol,因为resolve someSymbol将返回nil。事实证明,通过定义函数中某处的def,可以定义符号: (resolve 'someSymbol) (defn resolvePokus [] (prn "I was evaluated") (def someSymbol 1) ) (resolve 'someSymbol) 在REPL中,收益率: nil #'user/r
(resolve 'someSymbol)
(defn resolvePokus []
(prn "I was evaluated")
(def someSymbol 1)
)
(resolve 'someSymbol)
在REPL中,收益率:
nil
#'user/resolvePokus
#'user/someSymbol
这是否意味着在运行defn时会对某些特殊表达式求值?哪一个
对defn的源代码的简要调查并没有向我透露任何信息,除了在这个核心函数中有一条TODO注释:我假设您正在repl中运行。我没有看到你描述的行为:
clj.core=> (resolve 'someSymbol)
nil
clj.core=> (defn resolvePokus []
#_=> (prn "I was evaluated")
#_=> (def someSymbol 1)
#_=> )
#'clj.core/resolvePokus
clj.core=> (resolve 'someSymbol)
#'clj.core/someSymbol
; try to use it -> error "Unbound..."
clj.core=> someSymbol
#object[clojure.lang.Var$Unbound 0x542f6481 "Unbound: #'clj.core/someSymbol"]
clj.core=> (resolvePokus) ; run the function
"I was evaluated"
#'clj.core/someSymbol
clj.core=> (resolve 'someSymbol) ; still can resolve
#'clj.core/someSymbol
clj.core=> someSymbol ; now we can use it
1
clj.core=> (declare xyz) ; creates a var, but unbound
#'clj.core/xyz
clj.core=> (resolve 'xyz) ; we can see resolve it
#'clj.core/xyz
clj.core=> xyz ; try to use it -> error "Unbound"
#object[clojure.lang.Var$Unbound 0x2d1d436f "Unbound: #'clj.core/xyz"]
clj.core=> (def xyz 5) ; define it
#'clj.core/xyz
clj.core=> (resolve 'xyz) ; still can resolve
#'clj.core/xyz
clj.core=> xyz ; now we can use it
5
因此,当我定义函数时,在键入最后一个括号后,repl打印“clj.core/resolvePokus已定义,但未定义someSymbol”。最后的resolve调用仍然返回nil
但是,如果您进一步阅读,Clojure似乎在第一次看到def someSymbol 1时就相当于声明了someSymbol。当我手动声明xyz并稍后通过def xyz 5给它一个值时,您可以看到相同的行为
您可能希望了解隐藏变量的详细信息,以及它如何作为符号xyz和值5之间的匿名中介
另外,上面的例子是在Ubuntu 16.04、Clojure 1.8、Java 1.8上运行的,对不起,我错过了粘贴-最后一行是someSymb而不是someSymbol。正在修正中…你确定最终解决仍然返回零吗?我的REPL不这么认为:user=>resolve'someSymbol nil user=>defn resolvePokus[]\u=>prn我被评估了=>def someSymbol 1\u=>user/resolvePokus user=>resolve'someSymb nil user=>resolve'someSymbol'user/someSymbol user=>resolve'someSymbol'用户/someSymbol仔细阅读并可能刷新页面。resolve'someSymbol除第一次外不返回nil。但是,当defn resolvePokus。。。完成了。我完成了,第一个解析确实像预期的那样返回零。现在我明白了,在defn中,只发生了一些必要符号的声明,但在基础var中没有存储任何值,最终的解析在符号仍然未绑定时确认符号的存在。正当感谢您和Charles D.Time说得很清楚,顺便说一下,从函数内部重新绑定Var的根值是一种非常严重的代码味道。这就是说-这不是你应该做的事情。另外,你可能会看到someSymbol解析为什么-你会注意到,当它解析时,它是未绑定的-不绑定到1-直到函数被实际调用为止。@AlanThompson,它们所不同的并发语义被显式地记录下来。重新定义一个var可能是一个阻塞操作。@AlanThompson,……此外,与altervar root不同,def不提供原子性保证。请参见FYI-输入REPL时,将函数编译为字节码。编译器。