【问题标题】:Why implement functions in records?为什么要在记录中实现功能?
【发布时间】:2014-08-16 17:23:53
【问题描述】:

可以在记录(以及相关的类型)中实现协议。但是,我想知道如果这些特定功能只实现一次(即仅用于一种记录类型)或者所有记录都使用该特定功能的相同实现,是否有任何理由这样做。

为了说明,假设我有 Player 的记录。

(defrecord Player [x y hp inventory])

现在我有机会实现更新协议;

(defprotocol Update
  (update [this world]))

(defrecord Player [x y hp inventory]
  Update
  (update [this world] this))

或者,我可以为此编写一个单独的函数。

(defn update [player world] player)

两者之间有什么区别,效率还是其他方面?

【问题讨论】:

    标签: clojure record


    【解决方案1】:
    • update 的简单函数定义不会进行类型检查以确保您只是将 Players 传递给它,但定义的协议版本会这样做,并且会抛出 IllegalArgumentException .您可能需要这种类型的安全性。或者您可能只是想与其他人交流预期的参数类型,但还有其他方法可以做到这一点。

    • 协议版本更加冗长,增加了可能毫无用处的复杂性。您可能想要简单函数定义的简单性。

    我认为,在 Clojure 世界中,当需要权衡取舍时,更喜欢表达式的简单性而不是类型安全性的情况并不少见,但这取决于项目和程序员。就个人而言,我通常想要更简单的代码,但在某些情况下我会倾向于另一个方向。

    还有这些明显的考虑:

    • 协议版本可能会让人们感到困惑,因为协议通常用于允许多态行为,因此他们希望为多种记录类型定义协议。

    • 如果您预计将来需要多态性,您可能希望从一开始就使用协议设置您的代码。

    最后:

    • 我没有关于效率的答案。其他人可能对此有一些有用的说法。不过,您可以使用 Criterium 运行测试,看看您的代码是否存在差异。

    【讨论】:

    • 如果它有类型安全,我想要它。我不愿意使用 core.typed,因为它看起来很冗长。
    【解决方案2】:

    这应该是对火星回答的评论。

    关于效率... 根据“Clojure 的喜悦”第 2 版。 (好奇的第 216 页),调用具有协议方法的内联定义的方法比在通过扩展实现协议的对象上调用方法快几倍。

    【讨论】:

    • 我认为不应该是评论。它至少为 OP 的部分问题(我无法回答的部分)提供了部分答案。
    猜你喜欢
    • 2014-08-29
    • 2011-06-24
    • 2023-03-22
    • 2023-02-20
    • 2021-01-14
    • 1970-01-01
    • 2016-04-21
    • 2010-10-16
    • 2016-06-03
    相关资源
    最近更新 更多