Clojure def против defn для функции без аргументов - PullRequest
46 голосов
/ 16 декабря 2010

Я написал программу в clojure, но некоторые функции не имеют аргументов.Каковы будут преимущества кодирования таких функций как «def» вместо «defn» без аргументов?

Ответы [ 4 ]

109 голосов
/ 12 октября 2011
user=> (def t0 (System/currentTimeMillis))
user=> (defn t1 [] (System/currentTimeMillis))
user=> (t1)
1318408717941
user=> t0
1318408644243
user=> t0
1318408644243
user=> (t1)
1318408719361
73 голосов
/ 16 декабря 2010

def s оцениваются только один раз, тогда как defn s (с аргументами или без аргументов) оцениваются (выполняются) при каждом вызове.Поэтому, если ваши функции всегда возвращают одно и то же значение, вы можете изменить их на def s, но не иначе.

38 голосов
/ 16 декабря 2010

(defn name ...) - это просто макрос, который в любом случае превращается в (def name (fn ...), независимо от того, сколько у него параметров).

11 голосов
/ 06 декабря 2014

Специальная форма 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!

  • в виде лямбда-формы (анонимная функция), которая сначала оценивается как объект функции :
    (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, но внутри он создает анонимную функцию и затем привязывает к ней объект Var.Его второй аргумент становится телом этой функции, и он не оценивается "обычным" способом.Можно также сказать, что он оценивается, но как лямбда-форма - результатом оценки является функциональный объект, а не результат какого-то мгновенного вычисления.

Итак, запись:
(defn fun [] 1)

Синоним:
(def fun (fn [] 1))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...