Подтвердить что ты не робот

Clojure def vs defn для функции без аргументов

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

4b9b3361

Ответ 1

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

Ответ 2

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

Ответ 3

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

Ответ 4

Специальная форма def создает объект 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 [email protected]> (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))