为什么defn似乎在函数体内评估(def符号)?

时间:2017-04-17 16:40:54

标签: clojure

在玩Clojure时我写了一个函数,它依赖于someSymbol在第一次运行时未定义,因为(resolve someSymbol)将返回nil。事实证明,通过defn在其中的def处使用函数会导致符号被定义:

 (resolve 'someSymbol)
 (defn resolvePokus []
   (prn "I was evaluated")
   (def someSymbol 1)
   )
 (resolve 'someSymbol)

在REPL中产生:

nil
#'user/resolvePokus
#'user/someSymbol

这是否意味着,在运行defn时会评估一些特殊表达式?哪个?

简要介绍一下defn的来源并没有向我透露任何内容,除了这个核心功能中有一个TODO评论:)

1 个答案:

答案 0 :(得分:1)

我假设你在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第一次看到(declare someSymbol)时,它似乎相当于(def someSymbol 1)。当我手动(declare xyz)并稍后通过(def xyz 5)

为其提供值时,您可以看到相同的行为

您可能希望look at this answer.详细信息涉及“隐藏”变量及其如何是符号xyz和值5之间的匿名中介。

P.S。上面的例子是在Ubuntu 16.04,Clojure 1.8,Java 1.8

上运行的