2010-12-16 3 views
42

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

+6

ли вы имеете в виду `(DEF х (Fn [] (то)))` или `(DEF х (что-то)) `? Они совершенно разные, и принятый ответ верен только для второй интерпретации. – 2014-09-29 00:13:16

+1

Я думаю, второе слово, но хорошая точка! – Zubair 2014-09-29 07:02:27

ответ

61

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

+0

А, я не знал этого, ты спас меня от некоторых серьезных ошибок! Итак, если есть def, который обращается к ссылке, он никогда не будет пересчитан? Как насчет перезагрузки файла? – Zubair 2010-12-16 17:29:06

28

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

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

def специальная форма создает Var объект, идентифицированный символ данного в качестве первого аргумента. Идентификация создается путем связывания данного символа с помощью Var в карте называется пространством имен.

Вар проводит ссылку на какое-то значение, которое co ÜLD быть выражены (среди прочих):

  • как постоянная форма, которая всегда оценивает свое значение:
    (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))

Смежные вопросы