Функция Clojure в привязке let

Если у меня есть функция, которая оценивает функцию

(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 будет генерироваться на каждом шаге сокращения.


person Jason Ozias    schedule 04.06.2013    source источник


Ответы (1)


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

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

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

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

Затем вызовите reduce следующим образом:

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

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

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

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

Надеюсь, это поможет.

person juan.facorro    schedule 04.06.2013
comment
Да, это именно то, что я искал. Никогда не думал проверять это с побочным эффектом. Спасибо. - person Jason Ozias; 05.06.2013
comment
Также обратите внимание, что создание экземпляров функций, как правило, обходится дешево, поэтому, даже если бы было выделено несколько функций, это не было бы большой проблемой. Очевидно, вы можете создавать функции, которые дорого строить, но это не значит, что вам приходится каждый раз перекомпилировать функцию (я упоминаю об этом, потому что новички в закрытии часто компилируют их каждый раз, когда они создаются). - person amalloy; 05.06.2013