我在clojure中编写了一个程序,但是有些函数没有参数.将这样的函数编码为"def"而不是没有参数的"defn"会有什么好处?
jam*_*qiu 112
user=> (def t0 (System/currentTimeMillis))
user=> (defn t1 [] (System/currentTimeMillis))
user=> (t1)
1318408717941
user=> t0
1318408644243
user=> t0
1318408644243
user=> (t1)
1318408719361
Run Code Online (Sandbox Code Playgroud)
Abh*_*kar 76
defs只被评估一次,而defns(有或没有参数)在每次被调用时被评估(执行).因此,如果您的函数始终返回相同的值,则可以将它们更改为defs,但不能更改为s.
sie*_*fca 11
的def特殊形式创建一个无功由下式给出作为它的第一个参数的象征识别的对象.通过将给定符号与名为namespace的映射中的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绑定到此求值的结果.
甚至fn在之前进行过求值,但其结果值是一个包含代码的函数对象.每次调用函数时都将执行(和评估)此代码.这就是为什么会有不同的结果.
该defn宏只是喜欢def,但在内部它会创建一个匿名函数,然后结合一个无功反对.它的第二个参数成为这个函数的一个主体,它没有以"常规"的方式进行评估.也可以说它被评估但是作为一种lambda形式 - 评估的结果是一个函数对象,而不是一些即时计算的结果.
所以写:
(defn fun [] 1)
是同义词:
(def fun (fn [] 1))