Defmulti vs Defmethod有什么区别?在Clojure

发布于 2025-02-11 10:55:23 字数 455 浏览 2 评论 0 原文

Defmethod&amp之间有什么区别; Defmulti ??

提到这些链接。但是它仍然不清楚。

  1. https://clojurecs.org/clojure.core.core.core.core/defmulti

https://clojuredocs.org/clojure.core.core.core.core/defmethod 简单的例子?

What is the difference between defmethod & defmulti??

Referred to these links. But its still not clear..

  1. https://clojuredocs.org/clojure.core/defmulti
  2. https://clojuredocs.org/clojure.core/defmethod

Can someone please help me with the simple example?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

放飞的风筝 2025-02-18 10:55:23

关于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

(defmulti print-method (fn [x writer]
                         (let [t (get (meta x) :type)]
                           (if (keyword? t) t (class x)))))

其第一个参数的类型/类。

然后在许多地方实施,特别是 core_print.clj
例如,对于关键字,它是这样实现的:

(defmethod print-method clojure.lang.Keyword [o, ^Writer w]
  (.write w (str o)))

另一个很好的例子是 instant.clj 提供了一些与日期相关类型的打印机实现。

print-method 还具有默认实现

(defmethod print-method :default [o, ^Writer w]
  (if (instance? clojure.lang.IObj o)
    (print-method (vary-meta o #(dissoc % :type)) w)
    (print-simple o w)))

将“ print-method”定义为多途径不仅允许clojure本身分开各种类型的实现,而且还为语言用户提供了“开放扩展”机制。
也就是说,您可以为您的自定义类型实现打印方法以很好地打印它们。
一个例子是

;; pr and prn support to write edn
(defmethod print-method org.joda.time.DateTime
  [v ^java.io.Writer w]
  (.write w (to-edn v)))

最后,一个小提示: defmulti use defonce 在引擎盖下方,以便重新定义其定义(调度函数) ,您可以使用以下技巧:

(def my-multi-method nil)
(defmulti my-multi-method ...)

第一个 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-L3666

(defmulti print-method (fn [x writer]
                         (let [t (get (meta x) :type)]
                           (if (keyword? t) t (class x)))))

You 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:

(defmethod print-method clojure.lang.Keyword [o, ^Writer w]
  (.write w (str o)))

Another good example is instant.clj which provides a few print-method implementations for date-related types.

print-method also has the default implementation

(defmethod print-method :default [o, ^Writer w]
  (if (instance? clojure.lang.IObj o)
    (print-method (vary-meta o #(dissoc % :type)) w)
    (print-simple o w)))

Having 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

;; pr and prn support to write edn
(defmethod print-method org.joda.time.DateTime
  [v ^java.io.Writer w]
  (.write w (to-edn v)))

Finally, a small tip: defmulti uses defonce under the hood so to redefine its definition (the dispatch function) while you are working on it, you can use this trick:

(def my-multi-method nil)
(defmulti my-multi-method ...)

The first def will make sure to replace whatever my-multi-method points to so you can get the fresh definition without restarting the REPL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文