2013-11-22 5 views
23

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

+2

Смотрите также вопрос: http://stackoverflow.com/ Вопросы/15747774/whats-the-point-of-define-something-as-dynamic-when-you-dont-need-to-define/15748334 # 15748334 – Alex

ответ

25

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

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

Примеры:

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,]> 
+3

Все это почему 'with-redefs' предназначено для использования в тестах (там, где вы можете захотеть получить и закрыть функцию), которая «привязка» может быть полезна в производственном коде как w флигель. – Peeja

Смежные вопросы