我应该在哪里使用defrecord在clojure?

时间:2011-01-01 18:36:52

标签: clojure

我在我的clojure程序中使用了很多地图和结构。将这些转化为辩证的有什么好处(除了表现)?

5 个答案:

答案 0 :(得分:87)

我认为结构有效地被弃用,所以我根本不使用它们。

当我在许多地图实例中使用一组固定的已知密钥时,我通常会创建一条记录。最大的好处是:

  • 性能
  • 生成的类具有可以在多方法或其他情况下打开的类型
  • 使用defrecord附近的其他宏机制,我可以获得字段验证,默认值以及我想要的任何其他东西
  • 记录可以实现任意接口或协议(地图不能)
  • 记录充当大多数用途的地图
  • keys和val以稳定(按创建)顺序返回结果

记录的一些缺点:

  • 因为记录是Java类实例(不是Clojure映射),所以没有结构共享,因此相同的记录结构可能会使用比已更改的等效映射结构更多的内存。当您“更改”记录时,还会有更多的对象创建/破坏,尽管JVM专门设计用于吃掉这种短暂的垃圾而不会出汗。
  • 如果您在开发期间更改记录,则可能需要更频繁地重新启动REPL以获取这些更改。这通常只是在开发过程中的一个问题。
  • 许多现有的库尚未更新以支持记录(postwalk,zip,matchure等)。我们已根据需要添加了此支持。

答案 1 :(得分:14)

Stuart Sierra最近撰写了一篇关于“用Clojure 1.2解决表达式问题”的有趣文章,该文章还包含defrecord的一节:

http://www.ibm.com/developerworks/java/library/j-clojure-protocols/index.html#datatypes

我认为整篇文章是理解协议和记录的良好起点。

答案 2 :(得分:9)

另一个主要好处是记录有一个你可以派出的类型(它的类)。

使用此功能但不能代表所有可能用途的示例如下:

(defprotocol communicate
  (verbalize [this]))

(defrecord Cat [hunger-level]
  communicate
  (verbalize [this]
    (apply str (interpose " " (repeat hunger-level "meow")))))

(defrecord Dog [mood]
  communicate
  (verbalize [this]
    (case mood
      :happy "woof"
      "arf")))

(verbalize (->Cat 3))
; => "meow meow meow"

(verbalize (->Dog :happy))
; => "woof"

答案 3 :(得分:2)

在大多数情况下使用地图,仅在需要多态时才使用记录。仅使用地图,您仍然可以使用多方法;但是,如果您需要协议,则需要记录。鉴于此,请等到您需要协议才能使用记录。在此之前,请避免使用更多以数据为中心且更简单的代码。

答案 4 :(得分:0)

除了之前已经提到的内容之外,除了在性能方面通常处于同等或更高水平,并且在将相同的编程接口暴露为地图之外,记录还强制执行温和的结构:密钥名称和密钥数量在定义的时间。这可能有助于避免愚蠢错误,其中许多值需要相同的结构(否则只是人为刚性)。

无论原始动机是什么,这个属性也将它与地图区分开来。