11

所以我想用java.awt.Color一些东西,我希望能够编写这样的代码:

(use 'java.awt.Color)
(= Color/BLUE (- Color/WHITE Color/RED Color/GREEN))

查看 的核心实现-,它专门讨论clojure.lang.Numbers,这对我来说意味着我没有做任何事情来“挂钩”核心实现并对其进行扩展。

在互联网上环顾四周,人们似乎做了两种不同的事情:

  • 编写他们自己的defn -函数,该函数只知道他们感兴趣的数据类型。要使用你可能最终会为命名空间添加前缀,例如:

    (= Color/BLUE (scdf.color/- Color/WHITE Color/RED Color/GREEN))

    或者,在需要数字数学时use使用命名空间并使用。clojure.core/-

  • 将一个特殊情况编码到您的-实现中,clojure.core/-当您的实现通过Number.

不幸的是,我不喜欢其中任何一个。第一个可能是最干净的,因为第二个假设您唯一关心的数学运算是它们的新数据类型和数字。

我是 Clojure 的新手,但我们不应该在这里使用协议或多方法,这样当人们创建/使用自定义类型时,他们可以“扩展”这些功能,让它们无缝工作吗?+有没有理由-不支持这个?(或者是吗?从我阅读代码来看,它们似乎不是,但也许我读错了)。

如果我想为常见的现有函数(例如其他数据类型)编写自己的扩展+,我应该怎么做才能很好地与现有函数和可能的其他数据类型一起使用?

4

3 回答 3

5

它并非完全为此而设计,但您可能会对core.matrix感兴趣,原因如下:

  • 源代码提供了如何使用协议来定义使用各种不同类型的操作的示例。例如,(+ [1 2] [3 4]) => [4 6])。值得研究如何做到这一点:基本上操作符是调用协议的常规函数​​,并且每种数据类型通过以下方式提供协议的实现extend-protocol
  • 您可能有兴趣将java.awt.Color工作作为 core.matrix 实现(即作为 4D RGBA 向量)。我在这里用 BufferedImage 做了类似的事情:https ://github.com/clojure-numerics/image-matrix 。如果您实现了基本的 core.matrix 协议,那么您将获得整个 core.matrix API 来处理Color对象。这将为您节省大量实施不同操作的工作。
于 2013-05-12T02:13:11.577 回答
4

不在基于协议的核心中进行算术运算(并使它们仅对数字起作用)的可能原因是性能。协议实现需要额外的查找来选择所需功能的正确实现。虽然从设计的角度来看,拥有基于协议的实现并在需要时扩展它们可能感觉很好,但是当你有一个紧密循环多次执行这些操作时(这是算术运算的常见用例),你会开始感觉由于在运行时发生的每个操作的额外查找导致的性能问题。

如果您在自己的命名空间中有自己的数据类型(例如:)的单独实现,color/-那么由于直接调用该函数,它将具有更高的性能,并且它还使事情更加明确和可针对特定情况进行定制。

这些函数的另一个问题是它们的可变特性(即它们可以接受任意数量的参数)。这是提供协议实现的一个严重问题,因为协议扩展类型检查仅适用于第一个参数。

于 2013-05-12T07:42:17.060 回答
2

您可以algo.generic.arithmeticalgo.generic中查看。它使用多种方法。

于 2013-06-11T11:02:16.177 回答