功能映射与协议实现

时间:2013-10-23 07:41:13

标签: clojure idioms

我是clojure的新手,我正在尝试理解不同情况下可用的不同设计选择。在这种特殊情况下,我想将紧密耦合的功能组合在一起,并且可以将函数作为集合传递。

  1. 何时使用功能图分组紧密相关的功能以及何时使用协议(+实现)?

  2. 有哪些优点和缺点?

  3. 要么更惯用吗?

  4. 供参考,以下是我的意思的两个例子。使用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))
    

3 个答案:

答案 0 :(得分:1)

这完全取决于“紧密相关的功能”的含义。可以有两种解释:

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

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

答案 1 :(得分:1)

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

如果您只是尝试将某个地方related functions分组使用namespace,则可以将您的功能浮动到那里,而不是特定的Object

在我看来,你正在考虑对象并使用map来模拟一个对象或一个结构,你将你的功能连接在一起。感觉不自然,除非它确实是一种类型或协议,在这些情况下你应该使用defrecorddeftypedefprotocol

关于使用defprotocoldefrecord

from here示例
(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")))

答案 2 :(得分:0)

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