我应该在clojure中使用defrecord?

我在我的clojure程序中使用了许多地图和结构。 将这些转换为defrecords有什么好处(除了性能)?

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

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

  • 性能
  • 生成的类有一个我可以在multimethods或其他情况下打开的types
  • 有了defrecord附加的macros机制,我可以得到字段validation,默认值,以及任何我想要的东西
  • logging可以实现任意的接口或协议(地图不能)
  • logging充当大多数目的的地图
  • 键和val返回稳定(按照创build)顺序的结果

logging的一些缺点:

  • 因为logging是Java类实例(不是Clojure地图),所以没有结构共享,因此相同的logging结构可能会使用比等效的已更改的地图结构更多的内存。 虽然JVM是专门devise用来吃掉这种短命的垃圾而不用冒汗的,但是“更改”logging的时候也有更多的对象创build/销毁。
  • 如果您在开发过程中更改logging,则可能需要更频繁地重新启动REPL才能获取这些更改。 这通常只是在狭窄的发展阶段的一个问题。
  • 许多现有的图书馆没有更新,以支持logging(邮政,邮编,比赛等)。 我们已经根据需要添加了这个支持。

Stuart Sierra最近写了一篇关于“用Clojure 1.2解决expression问题”的有趣文章,其中还包含了关于defrecord一节:

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

我认为整篇文章是理解协议和logging的一个很好的起点。

另一个主要的好处是logging有一个types(它的类),你可以派遣。

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

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

在大多数情况下使用地图,只有在需要多态时才使用地图。 单独使用地图,您仍然可以使用多种方法; 但是,如果您需要协议,则需要logging。 考虑到这一点,等到你需要协议后再诉诸logging。 在此之前,请避免使用更多以数据为中心和更简单的代码。

除了之前提到的,除了在性能方面一般都处于同等水平或者更高的地位之外,以及将相同的编程接口作为地图公开,logging实施了一种温和的结构:密钥名称和密钥数目在定义。 这可能对避免愚蠢的错误很有用,因为在许多数值上可能会出现同样的结构(否则就是人为地僵化)。

无论最初的动机是什么,这个属性也将它与地图区别开来。