Clojure - 在地图上使用记录有什么好处

new*_*Dev 6 functional-programming clojure diamond-problem

我很难决定何时使用defrecord是正确的选择,更广泛地说,我在我的记录中使用的协议是否符合语义 clojure 和功能性。

在我当前的项目中,我正在构建一个游戏,该游戏具有不同类型的敌人,它们都具有相同的一组动作,这些动作可能以不同的方式实现。

来自 OOP 背景,我很想做这样的事情:

(defprotocol Enemy
  "Defines base function of an Enemy"
  (attack [this] "attack function"))

(extend-protocol Enemy
  Orc
  (attack [_] "Handles an orc attack")  
  Troll
  (attack [_] "Handles a Troll attack"))



(defrecord Orc [health attackPower defense])
(defrecord Troll [health attackPower defense])

(def enemy (Orc. 1 20 3))
(def enemy2 (Troll. 1 20 3))

(println (attack enemy))
; handles an orc attack

(println (attack enemy2))
;handles a troll attack

Run Code Online (Sandbox Code Playgroud)

这从表面上看似乎是有道理的。我希望每个敌人总是有一种攻击方法,但实际实施应该能够因特定的敌人而异。使用extend-protocol我能够创建有效的调度方法,根据我的敌人而变化,我可以轻松添加新的敌人类型以及更改这些类型的功能。

我遇到的问题是为什么我应该在通用地图上使用记录?以上对我来说有点 OOP 的感觉,似乎我反对更实用的风格。所以,我的问题分为两个:

  1. 我上面的记录和协议实现是一个合理的用例吗?
  2. 更笼统地说,什么时候记录比地图更受欢迎?我已经读过,当您多次重新构建同一张地图时,您应该更喜欢记录(就像我在这种情况下所做的那样)。这个逻辑合理吗?

Sea*_*eld 7

这个流程图仍然是很好的建议,九年后:https : //cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/——似乎已经转移到https://cemerick.com/blog/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form.html

我的经验法则是:始终使用普通哈希映射,直到您确实需要多态性,然后再决定是否需要多方法(调度一个或多个参数/属性)或协议(仅调度类型)。

  • 我找到了一个更新的链接,并将其添加到原始答案中。 (4认同)