【问题标题】:Function map vs protocol implementation功能图与协议实现
【发布时间】:2013-11-01 09:00:37
【问题描述】:

我是 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))

【问题讨论】:

    标签: clojure idioms


    【解决方案1】:

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

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

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

    【讨论】:

    • 那么什么时候应该使用函数映射呢?
    • 我个人,不会使用函数映射,只使用映射数据
    【解决方案2】:

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

    如果您只是想将related functions 分组到某个地方,请使用namespace,可以让您的函数浮动到没有特定的Object

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

    from here 为例,使用defprotocoldefrecord

    (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")))
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多