Clojure

学习 Clojure - 顺序集合

Clojure 集合将值“收集”到复合值中。有四种主要的 Clojure 集合类型:向量、列表、集合和映射。在这四种集合类型中,向量和列表是有序的。

向量

向量是一种索引的、顺序的数据结构。向量用 [ ] 表示,如下所示

[1 2 3]

索引访问

“索引”意味着可以使用索引检索向量的元素。在 Clojure 中(与 Java 一样),索引从 0 开始,而不是 1。使用 get 函数检索指定索引处的元素

user=> (get ["abc" false 99] 0)
"abc"
user=> (get ["abc" false 99] 1)
false

如果使用无效索引调用 get,则返回 nil

user=> (get ["abc" false 99] 14)
nil

count

所有 Clojure 集合都可以进行计数

user=> (count [1 2 3])
3

构建

除了文字 [ ] 语法之外,Clojure 向量还可以使用 vector 函数创建

user=> (vector 1 2 3)
[1 2 3]

添加元素

元素使用 conj(连接的缩写)添加到向量中。元素始终添加到向量的末尾

user=> (conj [1 2 3] 4 5 6)
[1 2 3 4 5 6]

不可变性

Clojure 集合与字符串和数字等简单值共享重要的特性,例如不可变性和按值比较相等性。

例如,让我们创建一个向量并使用 conj 对其进行修改。

user=> (def v [1 2 3])
#'user/v
user=> (conj v 4 5 6)
[1 2 3 4 5 6]

这里 conj 返回了一个新向量,但如果我们检查原始向量,我们会发现它没有改变

user=> v
[1 2 3]

任何“更改”集合的函数都会返回一个新实例。您的程序需要记住或传递更改后的实例才能利用它。

列表

列表是顺序的链表,它们将新元素添加到列表的头部,而不是像向量一样添加到尾部。

构建

因为列表通过将第一个元素作为函数来调用进行评估,所以我们必须引用列表以防止评估

(def cards '(10 :ace :jack 9))

列表没有索引,因此必须使用 firstrest 来遍历它们。

user=> (first cards)
10
user=> (rest cards)
'(:ace :jack 9)

添加元素

conj 可用于向列表添加元素,就像对向量一样。但是,conj 始终在可以对数据结构进行恒定时间操作的地方添加元素。对于列表,元素被添加到前面

user=> (conj cards :queen)
(:queen 10 :ace :jack 9)

栈访问

列表也可以用作带有 peek 和 pop 的栈

user=> (def stack '(:a :b))
#'user/stack
user=> (peek stack)
:a
user=> (pop stack)
(:b)