列表
基础知识
可以使用 list
函数构建列表
CL-USER> (list 1 2 3)
(1 2 3)
可以使用 first
、second
,一直到 tenth
来访问列表中的对应元素
CL-USER> (first (list 1 2 3))
1
CL-USER> (second (list 1 2 3))
2
这些元素还可以用于设置元素
CL-USER> (defparameter my-list (list 1 2 3))
MY-LIST
CL-USER> (setf (second my-list) 7)
7
CL-USER> my-list
(1 7 3)
更一般的,可以使用 nth
函数
CL-USER> (nth 1 (list 1 2 3))
2
并且它适用于 setf
CL-USER> (defparameter my-list (list 1 2 3))
MY-LIST
CL-USER> (setf (nth 1 my-list) 65)
65
CL-USER> my-list
(1 65 3)
高阶函数
Map
map
函数接收一个函数和一个列表,遍历序列中的每个元素,并返回一个新列表,其中每个元素都是使用原始元素调用该函数的结果。
例如
CL-USER> (mapcar #'evenp (list 1 2 3 4 5 6))
(NIL T NIL T NIL T)
等同于
CL-USER> (list (evenp 1) (evenp 2) (evenp 3) (evenp 4) (evenp 5) (evenp 6))
(NIL T NIL T NIL T)
另一个例子
CL-USER> (mapcar #'string-upcase (list "Hello" "world!"))
("HELLO" "WORLD!")
帮助理解 mapcar
的一种方法是自己编写
CL-USER> (defun my-map (function list)
(if list
(cons (funcall function (first list))
(my-map function (rest list)))
nil))
MY-MAP
CL-USER> (my-map #'string-upcase (list "a" "b" "c"))
("A" "B" "C")
Reduce
reduce
函数可用于通过对列表的连续子集应用函数来将列表转换为标量。例如
CL-USER> (reduce #'+ (list 1 2 3))
6
你还可以使用自定义函数
CL-USER> (reduce #'(lambda (a b)
(* a b))
(list 10 20 30))
6000
以上等同于 (* 10 (* 20 (* 30)))
。为了更好地理解 reduce 的工作原理,我们可以使用 format
CL-USER> (reduce #'(lambda (a b)
(format t "A: ~A, B: ~A~%" a b)
(* a b))
(list 1 2 3 4 5 6))
A: 1, B: 2
A: 2, B: 3
A: 6, B: 4
A: 24, B: 5
A: 120, B: 6
720
排序
sort
函数允许你对序列进行排序
CL-USER> (sort (list 9 2 4 7 3 0 8) #'<)
(0 2 3 4 7 8 9)
解构
(defun destructure (list)
(destructuring-bind (first second &rest others)
list
(format t "First: ~A~%" first)
(format t "Second: ~A~%" second)
(format t "Rest: ~A~%" others)))
这会生成
CL-USER> (destructure (list 1 2 3 4 5 6))
First: 1
Second: 2
Rest: (3 4 5 6)
NIL