我看了一下参考资料:http://clojure.org/vars#Vars%20and%20the%20Global%20Environment http://clojure.org/vars#Vars%20and%20the%20Global%20Environment, http://clojuredocs.org/clojure_core/clojure.core/binding http://clojuredocs.org/clojure_core/clojure.core/binding
也Clojure 和 ^:dynamic https://stackoverflow.com/questions/11730828/clojure-and-dynamic and Clojure 动态绑定 https://stackoverflow.com/questions/12789350/clojure-dynamic-binding?rq=1
我还是不明白为什么需要binding
无论如何,我编写的每个程序都没有它们,我可以找到以传统方式编写示例的方法 - 我发现这更容易理解。是否有利用此的项目/编程范例的示例?
例如......在动物说话的例子中,你可以获得类似的效果:
(def dog {:name "Dog" :sound "Woof"})
(def cat {:name "Cat" :sound "Meow"})
(defn speak [animal]
(str (:name animal) " says " (:sound animal))
(println (speak dog))
(println (speak cat))
没有宏,没有动态绑定......仍然非常干净。
没有strictly对它们的需要:正如你正确地观察到的那样,你可以做任何你喜欢的事情,而不需要它们binding
,并且确实如果binding
不存在那么你可以使用宏和 Java 相对容易地重新实现它ThreadLocal
s.
然而,绑定作为一种传递方式很有用动态上下文到函数而不需要显式传递参数。
当您编写深度嵌套的高阶函数并且不想向调用堆栈中的每个函数添加额外的参数以便将某些值传递给嵌入内部的较低级别函数时,它特别有用。
以您的示例为基础:
(def ^:dynamic *loud-noises* false)
(defn speak [animal]
(str (:name animal) " says "
(let [sound (:sound animal)]
(if *loud-noises* (.toUpperCase sound) sound))))
(speak dog)
=> "Dog says Woof"
(binding [*loud-noises* true]
(speak dog))
=> "Dog says WOOF"
注意我不需要添加额外的参数speak
函数以获得不同的行为。在这种情况下添加额外的参数是微不足道的,但想象一下如果speak
函数被深深地埋藏在一个复杂的高阶函数中......
不过,我认为总体而言最好的建议是避免动态绑定,除非您确实需要它。如果可以的话,通常最好添加显式参数:直接参数可以更轻松地测试和推理函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)