我正在Clojure中开发一个具有多个子结构的复杂数据结构。
我知道我会希望随着时间的推移扩展这个结构,有时可能想要更改内部结构而不会破坏数据结构的不同用户(例如我可能想要将一个向量更改为一个hashmap,添加一些出于性能原因,或者采用Java类型的索引结构
我目前的想法是:
我认为这会有效,但我担心它开始看起来像很多“胶水”代码。它也可能反映了我对面向对象方法的更多熟悉。
在Clojure中推荐的方法是什么?
答案 0 :(得分:11)
我认为deftype
可能是要走的路,但是我会对访问器方法进行传递。相反,请查看clojure.lang.ILookup
和clojure.lang.Associative
;这些接口如果您为您的类型实现它们,将允许您使用get
/ get-in
和assoc
/ assoc-in
,从而提供更通用的解决方案(不是只有你能够改变底层实现,但也许你也可以使用在Clojure标准集合库之上构建的函数来操作你的结构。
有几点需要注意:
您应该从defrecord
开始,使用get
,assoc
&具有defrecord
,ILookup
,Associative
和IPersistentMap
的标准java.util.Map
实施的公司。你可能会用它走很长的路。
如果/当这些不再足够时,请查看emit-defrecord
的来源(Clojure来源中core_deftype.clj
中定义的私有函数)。它非常复杂,但它可以让您了解可能需要实施的内容。
deftype
和defrecord
目前都没有为您定义任何工厂功能,但您应该自己动手。完整性检查进入这些功能(和/或相应的测试)。
概念上越复杂的操作当然非常适合建立在get
&基础之上的协议功能。有限公司
哦,在Clojure的源代码中查看gvec.clj
,了解一些使用deftype
编写的严肃数据结构代码的示例。这里的复杂性与您在问题中描述的不同,但它仍然是Clojure中目前可供公众使用的少数自定义数据结构编程示例之一(当然它也是优质代码)。
当然,这正是我的直觉告诉我的。我不确定在这个阶段已经存在很多成熟习语的方式,deftype
实际上没有被释放的所有内容。 : - )