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

Clojure: привязка против-redefs

clojure.core имеет макросы привязки и with-redefs. Глядя на docstrings и примеры на clojuredocs.org, они, похоже, делают что-то очень похожее. В чем разница и какой из них следует использовать в ситуациях?

4b9b3361

Ответ 1

Clojure Vars может иметь привязки к потоку. binding использует их, в то время как with-redefs фактически изменяет корневую привязку (которая похожа на значение по умолчанию) var.

Другое отличие состоит в том, что binding работает только для :dynamic vars, а with-redefs работает для всех vars.

Примеры:

user=> (def ^:dynamic *a* 1)
#'user/*a*
user=> (binding [*a* 2] *a*)
2
user=> (with-redefs [*a* 2] *a*)
2
user=> (binding [*a* 2] (doto (Thread. (fn [] (println "*a* is " *a*))) (.start) (.join)))
*a* is  1
#<Thread Thread[Thread-2,5,]>
user=> (with-redefs [*a* 2] (doto (Thread. (fn [] (println "*a* is " *a*))) (.start) (.join)))
*a* is  2
#<Thread Thread[Thread-3,5,]>

Вы можете использовать (недокументированный) binding-conveyor-fn, чтобы передать потоковые локальные привязки в новые потоки:

user=> (binding [*a* 2] (doto (Thread. (#'clojure.core/binding-conveyor-fn (fn [] (println "*a* is " *a*)))) (.start) (.join)))
*a* is  2
#<Thread Thread[Thread-5,5,]>