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

Вызов функций Clojure с использованием синтаксиса var-quote

Иногда, просматривая код других людей Clojure, я вижу функцию, определенную через defn, а затем вызывается с использованием синтаксиса var-quote, например:

user> (defn a [] 1)
#'user/a
user> (a)   ; This is how you normally call a function
1
user> (#'a) ; This uses the var-quote syntax and produces the same result
1

В жизни я не могу понять разницу между этими двумя способами вызова функции. Я не могу найти ничего в документации evaluation, чтобы сказать, что происходит, когда оператор вызова является var, который может подсказать, почему второй форма была бы предпочтительнее. Они оба, кажется, отвечают тем же самым на binding назначения и цитирование синтаксиса.

Итак, может ли кто-нибудь указать образец кода, который иллюстрирует разницу между (a) и (#'a) выше?

Изменить: Я знаю, что var-quote можно использовать для перехода к var, который затенен лексической привязкой let, но это не похоже на код, который Я смотрю.

4b9b3361

Ответ 1

(#'a) всегда ссылается на var a, а (a) может быть затенен локальными привязками:

user> (defn a [] 1)
#'user/a
user> (let [a (fn [] "booh")] [(a) (#'a)])
["booh" 1]

Но большинство фактических применений вызова var-quote/function не вызывает выражение var-quote напрямую, а вместо этого кэширует его значение, чтобы конструкции более высокого порядка ссылались на текущее значение var a вместо его значения при передаче в

(defn a [] 1)
(defn my-call [f] (fn [] (+ 1 (f))))
(def one (my-call a))
(def two (my-call #'a))
(defn a [] 2)

user> (one)
2
user> (two)
3

Это в основном полезно для интерактивной разработки, где вы меняете какую-то функцию, которая обернута кучей других функций в других пакетах.

Ответ 2

Вторая форма позволяет обойти ограничения конфиденциальности, установленные clojure.

Так, например, если вы создаете библиотеку с частными функциями, но хотите протестировать их из отдельного пространства имен, вы не можете обращаться к ним напрямую. Но вы можете получить их с помощью синтаксиса var quote. Это очень полезно для этого.

Конфиденциальность clojure - это, по сути, форма автоматической документации, в отличие от конфиденциальности, которую вы видите на Java. Вы можете обойти это.

user> (defn- a [] 1)
#'user/a
user> (ns user2)
nil
user2> (user/a)
CompilerException java.lang.IllegalStateException: var: #'user/a is not public,    compiling:(NO_SOURCE_PATH:1) 
user2> (#'user/a)
1
user2>