【问题标题】:Abstracting away from data structure implementation details in Clojure从 Clojure 中的数据结构实现细节中抽象出来
【发布时间】:2010-06-24 13:26:40
【问题描述】:

我正在 Clojure 中开发一个具有多个子结构的复杂数据结构。

我知道随着时间的推移我会想要扩展这个结构,并且有时可能想要在不破坏数据结构的不同用户的情况下改变内部结构(例如,我可能想要将向量更改为哈希图,添加一些出于性能原因的某种索引结构,或合并 Java 类型)

我目前的想法是:

  • 使用各种访问器方法为整体结构定义协议
  • 创建一个小型函数库,用于导航数据结构,例如(query-substructure-abc param1 param2)
  • 使用 defrecord 或 deftype 实现数据结构,并使用定义为使用迷你库的协议方法

我认为这会起作用,尽管我担心它开始看起来像是很多“胶水”代码。此外,这可能也反映了我对面向对象的方法更加熟悉。

在 Clojure 中推荐的方法是什么?

【问题讨论】:

    标签: data-structures clojure encapsulation abstraction


    【解决方案1】:

    我认为deftype 可能是要走的路,但是我会通过访问器方法。相反,请查看clojure.lang.ILookupclojure.lang.Associative;这些是接口,如果您为您的类型实现它们,将允许您使用 get / get-inassoc / assoc-in,从而提供更通用的解决方案(您不仅可以更改底层实现,但也许还可以使用构建在 Clojure 标准集合库之上的函数来操作您的结构)。

    有几点需要注意:

    1. 您可能应该从defrecord 开始,使用getassoc & Co. 以及ILookupAssociativeIPersistentMapjava.util.Map 的标准defrecord 实现。你也许可以走很长的路。

      如果/当这些还不够时,请查看 emit-defrecord 的源代码(在 Clojure 的源代码中 core_deftype.clj 中定义的私有函数)。它相当复杂,但它会让您了解您可能需要实现什么。

    2. deftypedefrecord 目前都没有为您定义任何工厂函数,但您可能应该自己做。健全性检查进入这些函数(和/或相应的测试)。

    3. 概念上更复杂的操作当然非常适合建立在get & Co. 基础上的协议功能。

    哦,请查看 Clojure 源代码中的 gvec.clj,了解使用 deftype 编写的一些严肃的数据结构代码可能是什么样子的示例。这里的复杂性与您在问题中描述的不同,但它仍然是目前可供公众使用的 Clojure 中为数不多的自定义数据结构编程示例之一(它当然是质量非常好的代码)。

    当然,这只是我此时的直觉告诉我的。我不确定现阶段是否存在很多已建立的习语,deftype 实际上还没有发布。 :-)

    【讨论】:

    • 谢谢米哈尔!洞察力一如既往:-) 肯定会研究 ILookup 和 Associative 选项
    • 这是一个非常有用的答案!但是将近三年后,如果基于 1.5 中现在可用的功能来更新这个(或创建一个新的答案),那就太好了。我注意到的一件事是 defrecord 现在确实发出了工厂函数,不确定还有哪些其他更改可能会影响这个答案。
    • 我认为这个答案也可以使用更新——甚至 O'Reily Clojure 的书现在都说 clojure 的 defrecord 创建工厂函数。
    猜你喜欢
    • 1970-01-01
    • 2023-01-30
    • 2015-10-14
    • 2018-02-12
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 2019-12-01
    • 1970-01-01
    相关资源
    最近更新 更多