clojure.core имеет макросы привязки и with-redefs. Глядя на docstrings и примеры на clojuredocs.org, они, похоже, делают что-то очень похожее. В чем разница и какой из них следует использовать в ситуациях?
Clojure: привязка против-redefs
Ответ 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,]>