阿男的小窝

View the Project on GitHub

Clojure的四种基础数据结构

在Clojure Programming一书1当中,介绍了Clojure的四种数据结构。本文是读书笔记,附加一些Clojure源代码分析。

Clojure的四种基础数据结构:

代码举例(来自Clojure Programming书中:Chapter 3 Collections and Data Structures):

'(a b :name 12.5) ;; list
['a 'b :name 12.5] ;; vector
{:name "Chas" :age 31} ;; map
#{1 2 3} ;; set

我们可以查看上面的数据结构对应的Clojure实现classes:

user=> (class '(a b :name 12.5))
clojure.lang.PersistentList

user=> (class ['a 'b :name 12.5])
clojure.lang.PersistentVector

user=> (class {:name "Chas" :age 31})
clojure.lang.PersistentArrayMap

user=> (class #{1 2 3})
clojure.lang.PersistentHashSet

从上面的代码2,我们可以看到数据类型对应的Clojure classes。

在实现上面的4种数据结构之下,Clojure包含有7种抽象的数据类型:

上面这些抽象模型体现在Clojure的实现代码当中,就是各个接口的定义。比如Collection类型,在Clojure Programming一书当中(Chapter 3 Collections and Data Structures - Abstractions over Implementations - Collection)给出的定义如下:

All data structures in Clojure participate in the common collection abstraction. A collection is a value that you can use with the set of core collection functions:

  • conj to add an item to a collection
  • seq to get a sequence of a collection
  • count to get the number of items in a collection
  • empty to obtain an empty instance of the same type as a provided collection
  • = to determine value equality of a collection compared to one or more other collections

上面这些定义都可以在Clojure的源代码种找到对应的接口和相关方法。下面是相关接口:

下面这幅图展现了这些接口之间的extends关系,以及接口中的方法定义:

注意上面这些接口重的方法定义,这些方法决定了Clojure的数据结构的设计思路和使用方法。

在IPersistentCollection之下,我们可以看到更为细分的接口类型:

从上面的图中可以看到Stack,Set,Vector,Seq之间的关系。其中ISeq类型是Clojure设计当中很重要的一类数据。我们可以重点看一下ISeq接口和相关的实现:

在上面的设计当中,LazySeq是会在后续文章里面重点说明的对象。

  1. Emerick, Chas, Brian Carper, and Christophe Grand. Clojure Programming: Practical Lisp for the Java World. “ O’Reilly Media, Inc.”, 2012. 

  2. https://stackoverflow.com/questions/22647738/differences-between-type-and-class-in-clojure