对于没有参数的函数,Clojure def vs defn

Zub*_*air 47 clojure

我在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)

  • 所以没有人会错过这个关键点:正如Roman Bataev的评论暗示的那样,`(def t2(fn [](System/currentTimeMillis)))`会使`t2`表现得像`t1`. (17认同)
  • 谢谢.这个代码示例值得超过1000字的描述. (14认同)
  • `def`将值绑定到名称,`defn`定义一个函数并将其绑定到一个名称.[defn vs fn]的更多细节(https://clojure.org/guides/learn/functions#__code_defn_code_vs_code_fn_code) (2认同)

Abh*_*kar 76

defs只被评估一次,而defns(有或没有参数)在每次被调用时被评估(执行).因此,如果您的函数始终返回相同的值,则可以将它们更改为defs,但不能更改为s.

  • @MattFenwick skuro的观点是`defn`s只被评估一次,就像每个`def` - 在这种情况下,它定义了一个函数.但是,定义的函数的*body*可以被评估任意次.我认为这不是一个有用的区别,但他并没有说任何错误. (7认同)
  • 我说"defn"形式被重新评估似乎是错误的.正如在其他答案中指出的那样,`defn`在宏扩展时解析为`def`,并且它们确实在文件加载时仅被评估一次. (3认同)

Rom*_*aev 41

(defn name ...)只是一个变成(def name(fn ...)的宏,无论它有多少参数.所以它只是一个捷径.详见(doc defn).


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))