在Clojure中,您将如何惯用地为其他数据类型扩展算术函数?
所以我想用在Clojure中,您将如何惯用地为其他数据类型扩展算术函数?,clojure,protocols,multimethod,Clojure,Protocols,Multimethod,所以我想用java.awt.Color来做一些事情,我希望能够编写如下代码: (use 'java.awt.Color) (= Color/BLUE (- Color/WHITE Color/RED Color/GREEN)) 看看-的核心实现,它特别谈到了clojure.lang.Numbers,这对我来说意味着我不需要“钩住”核心实现并扩展它 环顾互联网,人们做的事情似乎有两种: 编写他们自己的defn-函数,该函数只知道他们感兴趣的数据类型。若要使用,可能会在名称空间前面加前缀,例如:
java.awt.Color
来做一些事情,我希望能够编写如下代码:
(use 'java.awt.Color)
(= Color/BLUE (- Color/WHITE Color/RED Color/GREEN))
看看-
的核心实现,它特别谈到了clojure.lang.Numbers
,这对我来说意味着我不需要“钩住”核心实现并扩展它
环顾互联网,人们做的事情似乎有两种:
- 编写他们自己的
函数,该函数只知道他们感兴趣的数据类型。若要使用,可能会在名称空间前面加前缀,例如:defn-
或者(=颜色/蓝色(scdf.Color/-颜色/白色/红色/绿色))
对名称空间进行加密,并在需要数字数学时使用使用
clojure.core/-
- 将一个特殊情况编码到
-
实现中,当您的实现被传递一个编号时,它将传递到
clojure.core/-
+
,-
等不支持此功能?(或者是吗?他们似乎并不是因为我读了代码,但也许我读错了)
如果我想为其他数据类型编写我自己对常见现有函数(如
+
)的扩展,我应该如何做才能使它与现有函数和潜在的其他数据类型很好地配合使用?它并不是专门为此设计的,但您可能对此感兴趣,原因如下:
- 源代码提供了如何使用协议定义与各种不同类型一起工作的操作的示例。例如,
。值得研究的是如何做到这一点:基本上,操作符是调用协议的常规函数,每种数据类型都通过(+[12][34])=>[46])
extend-protocol
- 您可能有兴趣将
用作core.matrix实现(即作为4D RGBA向量)。我在这里对BuffereImage做了类似的操作:。如果您实现了基本的core.matrix协议,那么就可以使用整个core.matrix API来处理java.awt.Color
对象。这将为您节省大量执行不同操作的工作Color
color/-
)有单独的实现,那么由于直接调用该函数,它的性能将更高,并且它还使特定情况下的内容更加明确和可定制
这些函数的另一个问题是它们的可变性质(即它们可以接受任意数量的参数)。在提供协议实现时,这是一个严重的问题,因为协议扩展类型检查仅对第一个参数有效。您可以在中查看
算法泛型算法。它使用多种方法。Heh,所以core.matrix
实际上是我的第二个示例的来源。使用协议?我将不得不重新阅读代码,因为我没有注意到!另外,这并没有涉及到原始-
实现的细节。那么,我们是说Clojure核心实现是硬的,您不能扩展它吗?如果我试着减去另外两种与向量无关的类型呢?我会按照core.matrix
所做的做,把我自己的层放在core的上面吗?所以我重新阅读了你的代码,现在我看到了它是如何工作的:这正是我所期望的core-
的工作方式!我猜不是因为a)它已经存在了一段时间,b)它比直接暗示的电话慢。我想知道,如果一个库只提供支持协议的算术替代方案(即core.matrix所做的),那么它是否有价值,所以有一种标准的方法来实现这一点。保持核心-
快速,但允许一个通用但较慢的替代方案来替代那些需要它的人。也许我太过工程化了,我在Java上呆的时间太长了……我想你需要弄清楚你说的是什么“算术替代方案”以及你打算支持什么类型。如果是针对类似数组的结构(向量、矩阵、张量等),那么core.matrix
已经满足了您的要求。如果是针对一些不同的构造,那么可能有一个新库的范围,但我想不出太多合理的情况(复数、四元数可能……?)P.S.我认为core.matrix
可以很好地处理特定的Color
情况,假设你想把它当作4D RGBA颜色向量。我也是Clojure的新手。为什么不能为此使用协议呢?如果您阅读core/+
的源代码,它就不使用协议,因此没有什么可挂接的。看看mikera的答案,然后按照他的代码,你会看到如何使用协议。