clojure-基本语法-集合(一)

本文详细介绍了Clojure编程语言中的List和Vector集合类型,包括如何创建、操作及区别。重点阐述了List的单向链表结构与Vector的高效索引访问特性,并通过代码示例展示常用操作函数,帮助开发者深入了解Clojure集合使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Clojure提供以下集合类型: list, vector, set, map。并且可以使用Java里面提供的集合类型。所有的clojure集合是不可修改的、异源的以及持久的。不可修改表示集合产生之后,不能从集合里面增加或删除元素。异源表示集合里面可以装任意类型的数据。持久的表示集合有更新时,更新之前的数据还在。CLojure以一种高效的,共享内存的方式来实现集合。 
因为clojure里面的集合是不可修改的,所以也就没有对集合进行修改的函数。相反clojure里面提供了一些函数从一个已有的集合来高效地创建新的集合。同时也有一些函数操作一个已有的集合(比如vector)来产生另外一种类型的集合(比如LazySeq), 这些函数有不同的特性。 
一、列表List 
Clojure的List是单向链表,在头部增加新元素。List形式以“(1,2,3)”符号表示 
创建list的方式: 
1、通过list创建(这里list是clojure定义的指向clojure.lang.PersistentList的creator方法的符号) 
Java代码  收藏代码
  1. user=> (list 1 2 3)  
  2. (1 2 3)  
  3. user=> (list "a" "b" "c")  
  4. ("a" "b" "c")  
  5. user=> (list "a" 1 2.3 'a :keyname)  
  6. ("a" 1 2.3 a :keyname)  


2、通过list*创建 
list*要求最后一个参数必须为集合 
Java代码  收藏代码
  1. user=> (list* 1 [2 3])  
  2. (1 2 3)  
  3. user=> (list* nil [1 2])  
  4. (nil 1 2)  
  5. user=> (list* 1 nil)  
  6. (1)  
  7. user=> (list* 1 ())  
  8. (1)  


3、通过其它方式创建: 
Java代码  收藏代码
  1. user=> '(1 2 3);'符号阻止对后面的表达式立即求值,与quote意义相同  
  2. (1 2 3)  
  3. user=> (quote (1 2 3))  
  4. (1 2 3)  
  5. user=> (range 1 10)  
  6. (1 2 3 4 5 6 7 8 9)  
  7. user=> (repeat 5 1)  
  8. (1 1 1 1 1)  


操作List的函数: 
这里只介绍常用函数。 
1、cons: 
cons函数通过一个已有的集合来创建一个新的包含更多元素的集合,其中新加的元素在最前面 
Java代码  收藏代码
  1. user=> (cons 1 (list 2 3 4 5))  
  2. (1 2 3 4 5)  
  3. user=> (cons (list 1 2) '(3 4 5))  
  4. ((1 23 4 5)  


2、conj: 
conj接收一个组合数据类型作为其第一个参数和任意数量的其它参数。并返回一个新的列表,这个列表将所有的其它参数连接到原来那个列表。conj函数也对Vector、Map、Set适用。 
Java代码  收藏代码
  1. user=> (conj (list 1 2 34);list在头部增加新元素,所以此处添加在起始位置  
  2. (4 1 2 3)  
  3. user=> (conj nil 2)  
  4. (2)  
  5. user=> (conj nil 2 3)  
  6. (3 2)  


3、peek: 
peek函数操纵一个单一的列表作为参数并返回列表中的第一个值 
Java代码  收藏代码
  1. user=> (peek '(2 3 4))  
  2. 2  
  3. user=> (peek (list nil "2" 3))  
  4. nil  


4、pop: 
pop函数操纵一个单一的列表作为参数并且返回一个去掉了首个元素的新列表 
Java代码  收藏代码
  1. user=> (pop '(2 3 4))  
  2. (3 4)  
  3. user=> (pop (list nil "2" 3))  
  4. ("2" 3)  


5、first: 
first返回列表第一个元素。在list中,first与peek效果相同,因为list是压栈操作元素 
Java代码  收藏代码
  1. user=> (first nil)  
  2. nil  
  3. user=> (first ())  
  4. nil  
  5. user=> (first (list 1 2 3))  
  6. 1  


6、rest: 
rest返回去除first之后剩下的集合 
Java代码  收藏代码
  1. user=> (rest '(1 2 3))  
  2. (2 3)  
  3. user=> (rest nil)  
  4. ()  
  5. user=> (rest ())  
  6. ()  

List是以单向链接列表的形式来实现的,在这一点上有利有弊。读取列表的第一个元素或者在列表头添加一个元素的操作都可以在常量时间内完成,然而访问列表的第N个元素却需要N次操作。 

二、向量Vector 
Vector支持高效地根据索引来访问元素,与数组类似。Vector形式以“[1,2,3]”符号表示 
创建Vector方式: 
1、vector: 
vector接收任意数量的参数并将它们的值组成一个Vector 
Java代码  收藏代码
  1. user=> (vector)  
  2. []  
  3. user=> (vector nil)  
  4. [nil]  
  5. user=> (vector 1 2 3)  
  6. [1 2 3]  
  7. user=> (vector (list 1 2 3))  
  8. [(1 2 3)]  


2、vec: 
vec接收一个单独的参数,可能是任何Clojure或Java的数据类型,然后将其元素的值作为参数组成一个新的向量 
Java代码  收藏代码
  1. user=> (vec (list 1 2 3))  
  2. [1 2 3]  
  3. user=> (vec [1 2 3])  
  4. [1 2 3]  
  5. user=> (vec '())  
  6. []  
  7. user=> (vec nil)  
  8. []  


3、vector-of: 
vector-of函数第一个参数指定Vector元素的类型,后面任意个参数作为元素,如果类型转换正确,则返回一个vector。vector-of第一个参数包括::int :long :float :double :byte :short :char or :boolean 
Java代码  收藏代码
  1. user=> (vector-of :int 1 2 3)  
  2. [1 2 3]  
  3. user=> (vector-of :int "1" "2")  
  4. ClassCastException java.lang.String cannot be cast to java.lang.Character  cloju  
  5. re.lang.RT.intCast (RT.java:1076)  


常用操作函数: 
1、conj: 
conj函数在List常用函数中已介绍过,在操作Vector时,代码如下: 
Java代码  收藏代码
  1. user=> (conj [1 2 3] [4])  
  2. [1 2 3 [4]]  
  3. user=> (conj [1 2 34);由于vector在尾部增加新元素,所以4添加在末尾  
  4. [1 2 3 4]  
  5. user=> (conj '(1 2 34);这里参数为list,由于list在头部增加新元素,所以4添加在1之前  
  6. (4 1 2 3)  
  7. user=> (conj ["a" 2 3.4] -1)  
  8. ["a" 2 3.4 -1]  
  9. user=> (conj ["a" "b"] ["c"])  
  10. ["a" "b" ["c"]]  


2、peek: 
peek返回vector中第一个值,与操作list的区别和conj一样 
Java代码  收藏代码
  1. user=> (peek [1 2 3])  
  2. 3  
  3. user=> (peek '(1 2 3))  
  4. 1  
  5. user=> (peek [])  
  6. nil  


3、pop: 
pop返回peek之后剩下的集合 
Java代码  收藏代码
  1. user=> (peek [1 2 3])  
  2. 3  
  3. user=> (pop [1 2 3])  
  4. [1 2]  
  5. user=> (peek '(1 2 3))  
  6. 1  
  7. user=> (pop '(1 2 3))  
  8. (2 3)  


4、get: 
get函数接收两个参数来操作vector。第一个参数是vector,第二个参数是一个整数索引。它返回给定索引处的值,若在索引处没有值,则返回nil 
Java代码  收藏代码
  1. user=> (get [1 2 31)  
  2. 2  
  3. user=> (get [1 2 34)  
  4. nil  


5、assoc: 
assoc接收三个参数:第一个是向量,第二个是整数索引,第三个是一个值。它返回一个新的向量,这个向量是原来那个向量在给定的索引处插入那个值的结果。如果索引超过了向量的长度,那么会引发一个错误。 
Java代码  收藏代码
  1. user=> (assoc [1 2 30 10)  
  2. [10 2 3]  
  3. user=> (assoc [1 2 33 10)  
  4. [1 2 3 10]  
  5. user=> (assoc [1 2 34 10)  
  6. IndexOutOfBoundsException   clojure.lang.PersistentVector.assocN (PersistentVect  
  7. or.java:136)  


6、subvec: 
subvec接收两个或三个参数。第一个是向量,第二个和第三个(如果有的话)是索引。它返回一个新向量,这个向量由原来那个向量的介于两个索引之间或者第一个索引到向量末尾(如果没有第二个索引)的部分组成 
Java代码  收藏代码
  1. user=> (subvec [12 3 4 5 6 72)  
  2. [4 5 6 7]  
  3. user=> (subvec [12 3 4 5 6 72 4)  
  4. [4 5]  


7、rseq: 
rseq接受一个向量参数,如果向量为空,则返回nil,如果不为空,则在常量时间内返回顺序逆转的新向量: 
Java代码  收藏代码
  1. user=> (rseq [])  
  2. nil  
  3. user=> (rseq [3 5 9 1 3])  
  4. (3 1 9 5 3)  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值