2

我是 clojure 的新手,我试图理解在不同情况下可用的不同设计选择。在这种特殊情况下,我想对紧密耦合的功能进行分组,并使其可以作为集合传递函数。

  1. 何时使用函数映射来对紧密相关的功能进行分组,何时使用协议(+ 实现)?

  2. 有哪些优点和缺点?

  3. 哪个更惯用?

作为参考,这里有两个例子来说明我的意思。使用 fn 地图:

(defn do-this [x] ...)
(defn do-that [] ...)
(def some-do-context { :do-this (fn [x] (do-this x)
                       :do-that (fn [] (do-that) }

在第二种情况下,

(defprotocol SomeDoContext
  (do-this[this x] "does this")
  (do-that[this] "does that")

(deftype ParticularDoContext []
  SomeDoContext
  (do-this[this x] (do-this x))
  (do-that[this] (do-that))
4

3 回答 3

1

这完全取决于您所说的“紧密相关的功能”是什么意思。可以有2种解释:

  • 这些功能集实现系统的特定组件/子系统。示例:日志记录、身份验证等。在这种情况下,您可能会使用 clojure 命名空间(AKA 模块)来对相关函数进行分组,而不是使用哈希映射。

  • 这些函数集在某些数据结构或类型或对象等上协同工作。在这种情况下,您将使用基于协议的方法,它允许临时多态性,以便新类型也可以提供这组功能。示例:任何接口类型的东西:可排序、可打印等。

于 2013-10-23T09:22:17.607 回答
1

协议就像Interfaces这样,如果您要创建的是一个协议,请使用协议。

如果您只是想在related functions某处使用 a进行分组namespace,则可以让您的函数漂浮在那里并没有附加到特定Object的 .

在我看来,您正在考虑对象并使用map只是来模拟对象或将您的功能附加在一起的结构。除非它确实是一种类型或协议,否则我觉得不自然,你应该使用defrecord,deftype并且defprotocol在这些情况下。

从这里获取的关于使用defprotocoland的示例defrecord

(defprotocol IAnimal
  "the animal protocol"
  (inner-report [o] "a report"))

(defrecord Dog []
  IAnimal
  (inner-report [o]
    (println "Woof Woof.\n")))

(defrecord Cat []
  IAnimal
  (inner-report [o]
    (println "Meow Meow.\n")))
于 2013-10-23T14:33:05.423 回答
0

我的第一印象是第一种方式是面向数据的,第二种方式是面向类型的。到目前为止,我更喜欢面向数据的。也许这个决定与 Alan Perlis 的名言有关:“在一个数据结构上运行 100 个函数比在 10 个数据结构上运行 10 个函数要好。”

于 2013-10-23T08:32:54.090 回答