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