clojure - 在 Clojure 中,何时应该使用记录或向量来表示异构节点类型的树?

标签 clojure tree types idioms

对于表示由不同节点类型组成的树,哪种更好的惯用 clojure 实践:

A.使用 deftype 或 defrecord 定义的几种不同类型的记录构建树:

(defrecord node_a [left right])
(defrecord node_b [left right])
(defrecord leaf [])

(def my-tree (node_a. (node_b. (leaf.) (leaf.)) (leaf.)))

B.用向量构建树,并使用指定类型的关键字:

(def my-tree [:node-a [:node-b :leaf :leaf] :leaf])

我看到的大多数 clojure 代码似乎都倾向于使用通用数据结构(向量、 map 等),而不是数据类型或记录。举个例子,Hiccup 使用向量 + 关键字的方法很好地表示了 html。

我们什么时候应该选择一种风格而不是另一种风格?

最佳答案

您可以将任意数量的元素放入向量中。一条记录有一定数量的字段。如果你想限制你的节点只有 N 个子节点,记录可能会很好,例如当二叉树时,节点必须只有左和右。但对于 HTML 或 XML 之类的内容,您可能希望支持任意数量的子节点。

使用向量和关键字意味着“扩展”支持的节点类型集就像将新关键字放入向量中一样简单。 [:frob "foo"] 在 Hiccup 中是可以的,即使它的作者从未听说过 frobing。使用记录,您可能必须为每个节点类型定义一个新记录。但随后您将获得捕获拼写错误和验证子节点的好处。 [:strnog "some bold text?"] 不会被 Hiccup 捕获,但 (Strnog. "foo") 将是一个编译时错误。

向量是 Clojure 的基本数据类型之一,您可以使用 Clojure 的内置函数来操作它们。想扩展你的树吗?只需conj到它上面,或者update-in,或者其他什么。您可以通过这种方式逐步构建您的树。对于记录,您可能会陷入构造函数调用的困境,否则您必须为构造函数编写大量包装函数。

似乎这部分可以归结为动态与静态的争论。就我个人而言,我会采用动态(向量+关键字)路线,除非有特定需要使用记录的好处。以这种方式编码可能更容易,并且对用户来说更灵活,但代价是用户更容易最终陷入困惑。但 Clojure 用户可能习惯于定期处理危险武器。 Clojure 在很大程度上是一种动态语言,保持动态通常是正确的做法。

关于clojure - 在 Clojure 中,何时应该使用记录或向量来表示异构节点类型的树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4101614/

相关文章:

clojure - 如何在头脑中阅读 Lisp/Clojure 代码

java - 以 HashMap<string,integer> 作为其类型对 TreeSet 进行排序

tree - WEKA - RandomForest 如何知道树何时太深?

C# 相当于 MySQL 数据和时间数据类型

sql-server - 数据类型 date 和 datetime 在 add 运算符中不兼容

amazon-web-services - 例如通过 amazonica 分配标签和公共(public)

clojure - 如何使用 test.check 生成随机图?

尽管进行了彻底检查,但在 Modelsim 上的仿真中类型不匹配的 VHDL 代码

performance - 了解 Clojure 转换器性能

algorithm - 讲解红黑树中的黑高算法