def 特殊形式创建一个 Var 对象,该对象由作为其第一个参数给出的符号标识。标识是通过将给定符号与名为命名空间的映射中的 Var 相关联来创建的。
Var 持有对某个值的引用,可以表示为(以及其他):
(def x 1)
x
;; => 1 ; x holds a reference to a number 1
(def x (+ 2 2))
x
;; => 4 ; x holds a reference to a number 4
- 作为一种 Java 方法形式,首先被评估为其结果值:
(def x (System/currentTimeMillis))
x
;; => 1417811438904 ; x holds a reference to a number 1417811438904
x
;; => 1417811438904 ; still the same number!
- 作为 lambda 形式(匿名函数),首先被评估为函数对象:
(def x (fn [] (System/currentTimeMillis)))
x
;; => #<user$x user$x@4c2b1826>
(x) ; function form, function evaluated
;; => 1417811438904
(x) ; function form, function evaluated
;; => 1417812565866
以上所有内容都有一个简单的规则。在def 特殊形式的情况下,作为其第二个参数给出的 S 表达式 递归评估 在创建绑定之前,因此生成的 Var 绑定到 this 的结果评估。
即使fn 之前也被评估过,但其结果值是一个包含代码的函数对象。 每次调用函数时都会执行(和评估)此代码。这就是为什么会有不同的结果。
defn 宏就像def,但在内部它创建一个匿名函数,然后将一个 Var 对象绑定到它。它的第二个参数成为这个函数的一个主体,它不是以“常规”方式评估的。也可以说它是被评估的,但它是一种 lambda 形式——评估的结果是一个函数对象,而不是一些即时计算的结果。
所以写:
(defn fun [] 1)
是同义词:
(def fun (fn [] 1))