是否有可能重载Clojure多方法在arity? [英] Is it possible to overload Clojure multi-methods on arity?

查看:123
本文介绍了是否有可能重载Clojure多方法在arity?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些代码使用多方法,并希望重载函数(在这种情况下,多功能),以便我可以传递一个更高阶的函数,以帮助测试,例如。

I have some code that uses multi-methods and would ideally like to overload the function (in this case, multi-function) so that I can pass in a higher order function to help with testing, for example.

以下是示例:

(ns multi)

(defn my-print [m] (println "The colour is" (:colour m)))

(defmulti which-colour-mm (fn [m f] (:colour m)))

(defmethod which-colour-mm :blue [m f] (f m))
(defmethod which-colour-mm :red [m f] (f m))
(defmethod which-colour-mm :default [m f] (println "Default: Neither Blue nor Red"))

(defn which-colour
  ([m] (which-colour-mm m my-print))
  ([m f] (which-colour-mm m f)))

(which-colour {:colour :blue :object :ball})
(which-colour {:colour :yellow :object :ball})
(which-colour {:colour :blue :animal :parrot} (fn [m] (println "The " (:animal m) "is" (:colour m))))



因此我的defn提供了arity重载,想知道defmethod是否支持这样的东西。 (我想你不会为每个defmethod声明做它。)

So my defn provides the arity overloading but I'm wondering if defmethod supports anything like this. (I guess you wouldn't want to do it for each defmethod declaration.)

这是最合适的(敢说, )方法,还是有更好的方法?

Is this the most suitable (dare I say, idiomatic) approach, or is there a better way?

推荐答案

有一个库的用户接口和类型接口。

This is perfectly fine. There is the "user" interface and the "type" interface of a library. They may be identical, but they don't have to.

用户界面在您的情况下 which-color 。 类型接口是 which-color-mm (确定,不是真的,但只是为了参数)。

The "user" interface is in your case which-colour. The "type" interface is which-colour-mm (ok, not really, but just for the sake of the argument). The user of your library does not need to know about the multimethod.

另一方面,有人提供了一种新的颜色 - 例如:purple

On the other hand someone providing a new colour - say :purple - does not have to care about multi-arity boilerplate. This is handled for him in which-colour.

这是一个完全有效的设计!

This is a perfectly valid design!

但是当然还有一个价格标签:假设你有一种颜色,这有一些更加繁琐的方式来做事情...现在,你被锁定在一个可能较慢的界面。

But of course there's a price tag: Suppose you have a colour, which has some more perfomant way to do things... Now, you are locked into a possible slower interface.

为了澄清这一点:假设你有一个集合接口。您提供了一个函数 - conj - 允许用户向集合中添加元素。它是这样实现的:

To clarify this a little: Suppose you have a collection interface. You provide a function - conj - which allows the user to add elements to the collection. It is implemented like this:

(defn conj
  [coll & elements]
  (reduce conj1 coll elements))

conj1 类型接口(例如,多方法或协议功能):它向集合添加一个元素。因此,提供新集合类型的人只需要实现添加单个参数的简单情况。并且自动地,新类型也将支持添加多个元素。

conj1 is the "type" interface (eg. a multimethod or protocol function): it adds one element to the collection. So someone supplying a new collection type has only to implement the simple case of adding a single argument. And automagically the new type will also support adding multiple elements.

但现在假设你有一个集合类型,这允许一个更快的方式添加几个元素,另一个。此功能现在无法使用。

But now suppose you have a collection type, which allows a faster way to add several elements than just adding one after the other. This capability cannot be used now.

因此,您可以使多方法/协议函数 conj 本身。现在的集合可以使用更快的方式。但是每个实现都必须提供多个元素样板。

So you make the multimethod/protocol function the function conj itself. Now the collection can use the faster way. But each implementation must provide the multiple elements boilerplate.

这是一个折衷,取决于你的决定。没有正确的方法(tm)。两者都可以被认为是惯用的。 (虽然我个人会尝试尽可能经常与第一个。)

This is a trade-off and up to your decision. There is not Right Way(tm). Both can be considered idiomatic. (Although I personally would try to go with the first one as often as possible.)

YMMV。

(defmulti which-colour-mm (fn [m & args] (:colour m)))
(defmethod which-colour-mm :blue
  ([m] (print m))
  ([m f] (f m)))

这篇关于是否有可能重载Clojure多方法在arity?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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