Clojure: обвързване срещу with-redefs

clojure.core има макросите свързвания и с-redefs. Разглеждайки документационните низове и примерите на clojuredocs.org, те изглежда правят нещо много подобно. Каква е разликата и кой трябва да използвам в какви ситуации?


person Miikka    schedule 22.11.2013    source източник
comment
Вижте също този въпрос: stackoverflow.com/questions/15747774/   -  person Alex    schedule 22.11.2013


Отговори (1)


Clojure Vars може да има локално обвързване на нишка. binding ги използва, докато with-redefs всъщност променя основното свързване (което е нещо като стойността по подразбиране) на променливата.

Друга разлика е, че binding работи само за :dynamic променливи, докато 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,]>
person opqdonut    schedule 22.11.2013
comment
Всичко това е причината with-redefs да е предназначен за използване в тестове (където може да искате да достигнете и да изтриете функция), което binding може да бъде полезно и в производствен код. - person Peeja; 29.09.2014
comment
@Peeja благодаря, с други думи, with-redefs никога не трябва да се използва в многонишков контекст? - person Erik Kaplun; 11.06.2019
comment
@opqdonut от юни 2019 г. документацията на Vars има раздел Обвързващо предаване, който подчертава future, send , send-off и pmap като притежаващи възможностите за обвързване на пренос — означава ли, че binding-conveyor-fn вече не е необходим? - person Erik Kaplun; 11.06.2019
comment
@ErikKaplun, binding-conveyor-fn не е необходим, ако използвате функциите, които споменахте. Въпреки това, ако създавате нишки с (Thread. ...), все още имате нужда от него. - person Miikka; 14.01.2020