clojure的动态变量和绑定的实际目的是什么? [英] what is the practical purpose of clojure's dynamic vars and binding?

查看:135
本文介绍了clojure的动态变量和绑定的实际目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看了一下参考资料: http://clojure.org/vars#Vars%20and %20the%20Global%20环境 http://clojuredocs.org/clojure_core/clojure.core/binding

I had a look at the references: http://clojure.org/vars#Vars%20and%20the%20Global%20Environment, http://clojuredocs.org/clojure_core/clojure.core/binding

以及 clojure和^:dynamic Clojure动态绑定

我仍然不明白为什么需要 binding ,因为我写的每个程序都没有他们,我可以找到方法写例子在常规方式 - 我觉得更容易理解。有没有使用这个项目/编程范例的例子?

I still don't understand why there is a need for binding at all as every program I have written have been without them and I can find ways to write the examples in the conventional way - which I find more understandable. Are there examples of projects/programming paradigms that make used of this?

例如...在动物说话的例子中,你可以得到类似的效果:

for example... in the animal speak example, you can get a similar effect with:

(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))

没有宏,没有动态绑定...还是很干净。

no macros, no dynamic binding... still very clean.

推荐答案

没有严格要求他们:你正确地观察到你可以做任何你喜欢没有 binding ,确实如果 binding 不存在,那么你可以使用宏和Java的 ThreadLocal s。

There isn't strictly a need for them: as you rightly observe you can do anything you like without binding, and indeed if binding didn't exist then you could re-implement it relatively easily using macros and Java's ThreadLocals.

绑定作为一种将动态上下文传递给函数的方法很有用而不需要显式传递参数。

Binding is however useful as a way of passing dynamic context to a function without needing to explicitly pass a parameter.

当您编写深层嵌套的高阶函数并且不希望为每个函数添加额外的参数时,这是特别有用的

It is particularly useful when you are composing deeply nested higher order functions and don't want to add extra parameters to every single function in the call stack in order to pass some value to the lower level functions embedded deep within.

建立你的例子:

(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 函数来获得不同的行为。在这种情况下添加一个额外的参数将是微不足道的,但是想象如果讲话函数深埋在复杂的高阶函数中...

Note I didn't need to add an extra parameter to the speak function to get different behaviour. Adding an extra parameter would be trivial in this case, but imagine if the speak function was buried deep within a complex higher order function.....

然而,我认为整体最好的建议是避免动态绑定,除非你真的需要它。通常最好添加显式参数,如果你可以:直接参数使它更容易测试和原因的功能。

Still, I think the best advice overall is to avoid dynamic binding unless you really need it. It is usually better to add explicit parameters if you can: direct parameters make it easier to test and reason about functions.

这篇关于clojure的动态变量和绑定的实际目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆