Defmulti vs Defmethod有什么区别?在Clojure
Defmethod&amp之间有什么区别; Defmulti ??
提到这些链接。但是它仍然不清楚。
https://clojuredocs.org/clojure.core.core.core.core/defmethod 简单的例子?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于So的问题已经存在类似的问题 - 我认为这可能会有所帮助:使用多疗法代替cond在clojure中有什么好处?
MultimEthods Clojure提供了用于实施多态性行为的机制之一。
与协议的协议不同,仅在协议函数的第一个参数的 type 上派遣,多方法允许您通过a nutyary dispatch dispatch函数进行调度提供
Defmulti
。这意味着
defmulti
定义了一个新的多途径 - 其名称,docstring,尤其是调度函数。但是它确实 单独定义了任何实现 - 它就像具有单个方法/函数的接口。
相比之下,
defmethod
用于实施 dectach函数返回的特定值的多方法。要理解的重要一件事是,
fefmulti
的调度函数采用与多种方法的实现完全相同的参数。您还可以提供一个默认实现,如果调度函数返回的值与任何现有实现都不匹配,则可以调用该实现。您可以通过
(DefMethod my-Multi-Method:default ...)
进行此操作。那里有许多示例,我建议您检查一些Clojure书籍,详细解释了这一点 - 例如编程Clojure,第三版将整个第9章专门针对Multimethods。
Clojure的喜悦(一般有关Clojure的一本出色而深刻的书)也有一些很好的例子,包括第9章中的
编译器
- 我在此处发布了示例:(它还提到了一些更复杂的概念,例如层次结构 - 请参见
derive
- 但这对于您目前不需要理解)。使用多方法的另一个很好的例子是clojure本身,例如
print-method
。它在clojure.core中定义: https://github.com/clojure/clojure/blob/clojure-1.11.1.1/src/clj/clojure/core.clj#l3664-l36666其第一个参数的类型/类。
然后在许多地方实施,特别是 core_print.clj 。
例如,对于关键字,它是这样实现的:
另一个很好的例子是 instant.clj 提供了一些与日期相关类型的打印机实现。
print-method
还具有默认实现将“ print-method”定义为多途径不仅允许clojure本身分开各种类型的实现,而且还为语言用户提供了“开放扩展”机制。
也就是说,您可以为您的自定义类型实现
打印方法
以很好地打印它们。一个例子是
最后,一个小提示:
defmulti
usedefonce
在引擎盖下方,以便重新定义其定义(调度函数) ,您可以使用以下技巧:第一个
def
将确保替换任何my-multi-method
点,以便您可以在不重新启动depp的情况下获得新的定义。There are already similar questions on SO - this one in particular I think might be helpful: What are the benefits of using multimethods instead of cond in Clojure?
Multimethods are one of the mechanisms Clojure provides for implementing polymorphic behavior.
Unlike protocols, that only dispatch on the type of the first argument of the protocol's functions, multimethods allow for arbitrary dispatch via a dispatch function that you provide with
defmulti
.That means
defmulti
defines a new multimethod - its name, docstring, and, in particular, the dispatch function.But it does not define any implementation on its own - it's like an interface with a single method/function.
In contrast,
defmethod
is used to implement the multimethod for a particular value returned by the dispatch function.One important thing to understand is that the dispatch function of
defmulti
takes the exact same arguments as the multimethod's implementations.You can also provide a default implementation that gets called if the value returned by the dispatch function does not match any of the existing implementations. You do this via
(defmethod my-multi-method :default ...)
.There are numerous examples out there and I recommend you check some of the Clojure books explaining this in detail - e.g. Programming Clojure, Third edition dedicates the whole chapter 9 to multimethods.
Joy of Clojure (an excellent and deep book about Clojure in general) also has some good examples, including
compiler
in chapter 9 - I have the examples published here: https://github.com/jumarko/clojure-experiments/blob/develop-performance/src/clojure_experiments/books/joy_of_clojure/ch09_data_and_code.clj#L144-L158(it also mentions some more complicated concepts like hierarchies - see
derive
- but that is not necessary for you to understand at this time).Another good example of using multimethods is Clojure itself, e.g.
print-method
. It is defined in clojure.core :https://github.com/clojure/clojure/blob/clojure-1.11.1/src/clj/clojure/core.clj#L3664-L3666You can see that this multimethod basically dispatches on the type/class of its first argument.
It is then implemented in numerous places, notably core_print.clj.
E.g. for keywords, it's implemented like this:
Another good example is instant.clj which provides a few print-method implementations for date-related types.
print-method
also has the default implementationHaving print-method defined as a multimethod not only allows Clojure itself to separate implementations for various types but also provides an "open extension" mechanism for the users of the language.
That is you can implement
print-method
for your custom types to print them nicely.One example of this is the clj-time library
Finally, a small tip:
defmulti
usesdefonce
under the hood so to redefine its definition (the dispatch function) while you are working on it, you can use this trick:The first
def
will make sure to replace whatevermy-multi-method
points to so you can get the fresh definition without restarting the REPL.