Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Clojure中,您将如何惯用地为其他数据类型扩展算术函数?_Clojure_Protocols_Multimethod - Fatal编程技术网

在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/-

不幸的是,这两个我都不喜欢。第一个可能是最干净的,因为第二个假设你唯一关心的是他们的新数据类型和数字

我是Clojure的新手,但我们不应该在这里使用协议或多方法,这样当人们创建/使用自定义类型时,他们就可以“扩展”这些函数,从而使它们工作得毫无意义吗?是否有理由
+
-
等不支持此功能?(或者是吗?他们似乎并不是因为我读了代码,但也许我读错了)


如果我想为其他数据类型编写我自己对常见现有函数(如
+
)的扩展,我应该如何做才能使它与现有函数和潜在的其他数据类型很好地配合使用?

它并不是专门为此设计的,但您可能对此感兴趣,原因如下:

  • 源代码提供了如何使用协议定义与各种不同类型一起工作的操作的示例。例如,
    (+[12][34])=>[46])
    。值得研究的是如何做到这一点:基本上,操作符是调用协议的常规函数,每种数据类型都通过
    extend-protocol
  • 您可能有兴趣将
    java.awt.Color
    用作core.matrix实现(即作为4D RGBA向量)。我在这里对BuffereImage做了类似的操作:。如果您实现了基本的core.matrix协议,那么就可以使用整个core.matrix API来处理
    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的答案,然后按照他的代码,你会看到如何使用协议。