在 Lisp 中,所有数据结构都由 cons cells 构建,即它们本质上是链表或二叉树或两者兼而有之(如果我错了请纠正我)。 Clojure 数据结构是列表、向量、映射 和集合。 Clojure 为这些数据结构合并了两个包容性抽象:集合 和序列。 Sequence 抽象定义了 first
、rest
和 cons
操作,其中 collection 抽象定义集合特定操作,例如 conj
和 into
。
map
和 filter
等 Clojure 核心函数在 sequence 抽象上运行,但接受任何数据结构并执行隐式转换。这些函数也是惰性的。这是否意味着默认情况下 Clojure 在内部将数据存储在更高效的数据结构中,例如索引数组,并且只在需要时切换到链表? Clojure 实际上是如何将集合转换为序列的?序列是以流方式使用迭代器从集合构建的,还是作为一个整体构建的,然后传递给消费者?
最佳答案
Clojure 中唯一的单链表数据结构是一个实际的 list
,例如:
(list 1 2 3)
其他一切都是高效的数据结构(即向量、 map )。
惰性序列(名义上)由当前值和生成下一个值的方法组成。计算后,元素将被缓存并且不会重新计算。
将集合转换为序列是一个实现细节,通常对最终用户而言并不重要。
原始的 map
和 filter
函数是惰性的,许多其他函数也是如此。然而,这已经够让人头疼的了(无法预测实现时间),因此急切/命令式版本 mapv
和 filterv
被添加到语言中。
关于Clojure 序列和集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54426458/