Clojure多方法与协议

Sea*_*lan 43 clojure multimethod

我是Clojure新手并且正在寻找何时使用协议以及何时使用多方法的一些具体示例.我知道协议通常适用于创建类型层次结构和典型的OOP事物,它们是在多方法之后添加到语言中的,并且协议通常具有更好的性能,所以我的问题是:

协议是否意味着取代多方法?如果没有,你能给我一个例子,我会使用多方法而不是协议吗?

mik*_*era 35

协议和多方法是互补的,适用于略有不同的用例.

  • 协议根据第一个参数的类型提供高效的多态分派.因为它能够利用一些非常有效的JVM功能,所以协议可以为您提供最佳性能.
  • Multimethods支持非常灵活的多态,可以根据方法参数的任何函数进行调度.多方法速度较慢但非常灵活

一般来说,我的建议是使用协议,除非你有一个需要多方法的特定情况.

您可能需要多方法的情况如下:

(defn balance-available? [amount balance] (> balance amount))

(defmulti withdraw balance-available?)

(defmethod withdraw true [amount balance] 
  (- balance amount))

(defmethod withdraw false [amount balance] 
  (throw (Error. "Insufficient balance available!")))
Run Code Online (Sandbox Code Playgroud)

请注意,由于以下两个原因,您无法在此处使用协议:

  • 调度函数需要使用两个参数来确定要使用的方法实现(即,它是多个调度的情况).
  • 你也无法区分第一个参数的类型(可能总是一个数值)


Art*_*ldt 34

多方法更强大,更昂贵,

当它们足够时使用协议,但如果你需要根据从火星上看到的月相来发送,那么多方法是你的最佳选择.

存在允许简单的东西保持简单的协议,并为clojure提供了一种生成与等效java相同的字节码的方法.似乎大多数人大多数时候都在使用协议.当我需要派遣多个参数时,我会使用多方法,尽管我不得不承认这只会出现一次,并且isa更少使用完整的层次结构(由我).所以简而言之,在需要时使用Multimethods

最好的例子在我的expierence中,就在core.clj的开头

  • 另一方面,如果你是一个Clojure新手并且你认为你需要多态性,那么你错了很有可能.在Clojure中,确定需要定义新的多态功能是非常罕见的. (13认同)
  • 协议迫使你放弃大量的动态.在重新加载时,它们会在开发过程中导致非常混乱的行为,并将您锁定为仅调度第一个参数的类型,这使得很难更改代码.议定书显然不简单; 它们是一种挂钩JVM的低级调度的方法,以便获得自托管所需的速度.Multimethods*很简单 - 它们只是具有调度功能的变量. (10认同)

M S*_*ith 6

正如亚瑟所提到的,多方法更强大,更昂贵.实际上,协议可以被认为是调度函数所在的多个方法的特例 class.当然,事实并非如此,因为协议不止于此.

如果你需要派遣第一个参数的类以外的东西,你需要使用多方法或重新设计.调度类型是协议的一个很好的用例.