2013-06-04 3 views
3

Если у меня есть функция, которая оценивает для функциифункция Clojure в пусть связывания

(defn func1 [c1 c2] 
    (fn [x1 x2] 
    ...do some stuff with c1 c2 x1)) 

, что я использую в других частях карты или уменьшить, это лучше использовать встроенный

(defn func2 [x y z] 
    (reduce (func1 x y) z (range 20))) 

или к сначала свяжите его

(defn func2 [x y z] 
    (let [ffunc (func1 x y)] 
    (reduce ffunc z (range 20)))) 

В первом случае я буду обеспокоен тем, что новая функция над x и y генерируется каждый шаг t через сокращение.

ответ

3

Оценка функции вызова (func1 x y) делается один раз в каждом случае.

Правило для вычисления вызова функции в Clojure состоит в оценке всех выражений, предоставляемых в качестве своих аргументов, и последующем вызове функции с этими значениями.

Если определить следующую функцию высшего порядка:

(defn plus [] 
    (println "calling plus") 
    +) 

, а затем вызвать уменьшить следующим образом:

(reduce (plus) [0 1 2 3]) 

Один calling plus распечатывается, показывающий функцию plus вызывается только один раз ,

То же самое происходит при использовании let формы:

(let [f (plus)] 
    (reduce f [0 1 2 3])) 

Надеется, что это помогает.

+0

Да, это именно то, что я искал. Никогда не думал проверить его с побочным эффектом. Благодарю. –

+0

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