Когда использовать `постоянно` в clojure, как и когда оцениваются его аргументы?

В принятом ответе на другой вопрос Установка Clojure" константы " во время выполнения используется Clojure функция constantly.

Определение constantly выглядит так:

(defn constantly
  "Returns a function that takes any number of arguments and returns x."
  {:added "1.0"}
  [x] (fn [& args] x))

Строка doc говорит, что она делает, а не почему ее можно использовать.

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

(declare version)

(defn -main
  [& args]
 (alter-var-root #'version (constantly (-> ...)))
 (do-stuff))

Таким образом, функция, возвращаемая постоянно, напрямую оценивается для ее результата. Я смущен, насколько это полезно. Я, вероятно, не понимаю, как x будет оцениваться с помощью и не обертываться "постоянно".

Когда мне следует использовать constantly и зачем это нужно?

Ответы

Ответ 1

Функция constantly полезна, когда API ожидает функцию, и вы просто хотите константу. Это имеет место в примере, представленном в вопросе.

Большинство функций alter-* (включая alter-var-root) принимают функцию, позволяющую вызывающему пользователю что-то модифицировать, основываясь на ее старом значении. Даже если вы просто хотите, чтобы новое значение было равным 7 (без учета старого значения), вам все равно нужно предоставить функцию (при условии, что только 7 приведет к попытке оценить ее, что не удастся). Таким образом, вы должны предоставить функцию, которая просто возвращает 7. (constantly 7) создает именно эту функцию, экономя усилия, необходимые для ее определения.

Изменить: Что касается второй части вопроса, constantly - обычная функция, поэтому ее аргумент вычисляется до построения константы. Таким образом, (constantly @myref) всегда возвращает значение, на которое ссылается myref во время вызова constantly, даже если оно будет изменено позже.