Clojure def vs定义一个没有参数的函数

我已经用clojure编写了一个程序,但是其中一些函数没有参数。 编写诸如“def”而不是“defn”而没有参数的函数的优点是什么?

def s只被评估一次,而defn s(有或没有参数)每次被调用时被评估(执行)。 所以如果你的函数总是返回相同的值,你可以将它们改为def否则不能。

 user=> (def t0 (System/currentTimeMillis)) user=> (defn t1 [] (System/currentTimeMillis)) user=> (t1) 1318408717941 user=> t0 1318408644243 user=> t0 1318408644243 user=> (t1) 1318408719361 

(defn name …)只是一个变成(def name(fn …)的macros,不pipe它有多less个参数,所以它只是一个快捷方式,详见(doc defn)。

def特殊forms创build一个由第一个参数给定的符号标识的Var对象。 通过将给定的符号与称为名称空间的映射中的Var相关联来创build标识。

瓦尔提到了一些价值 ,可以expression(除其他外):

  • 作为一个永恒的forms, 总是评估自己的价值
    (def x 1) x ; => 1 ; x holds a reference to a number 1

  • 作为一个函数forms,它首先被评估为它的结果值
    (def x (+ 2 2)) x ; => 4 ; x holds a reference to a number 4

  • 作为一个Java方法forms,它首先被评估为它的结果值
    (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特殊forms的情况下,作为其第二个参数给出的Sexpression式在创build绑定之前 recursion地求值 ,所以得到的Var被绑定到该评估的结果。

甚至fn之前也被评估过,但是它的结果值是一个保存代码的函数对象。 这个代码将在每次调用函数时执行(和评估)。 这就是为什么有不同的结果。

defnmacros就像def但在内部它创build一个匿名函数,然后绑定一个Var对象。 它的第二个参数成为这个函数的一个主体,它不是以“常规”的方式进行评估的。 也可以说,它是评估,但作为拉姆达forms – 评估的结果是一个函数对象,而不是一些即时计算的结果。

所以写作:
(defn fun [] 1)

是同义词:
(def fun (fn [] 1))