在 Common Lisp 中,和在其他语言里一样,数组是一组通过整数下标访问的元素。 元素的类型可以各不相同。 数组可以是多维的(而不只是一维的)。
make-array可以用来创建数组。
它的选项很多,但较简单的用法可以创建 N 维数组,把所有元素都初始化为同一个值,或者用另一个序列(比如列表)中的值来初始化数组。
它的第一个参数是一个列表,给出每个维度的大小。
(make-array '(4) :initial-element 3) ; => #(3 3 3 3)
(make-array '(2 2) :initial-element 'x) ; => #2A((X X) (X X))
(make-array '(3 3 3)
:initial-contents '(((a b c) (d e f) (g h i))
((j k l) (m n o) (p q r))
((s t u) (v w x) (y z &))))
; => #3A(((A B C) (D E F) (G H I))
((J K L) (M N O) (P Q R))
((S T U) (V W X) (Y Z &)))
(注意 N 维数组在打印时带有维度数)
也可以直接用数组打印时的格式来创建数组:
#(x y z) ; => #(X Y Z)
#2A((1 2) (3 4)) ; => #2A((1 2) (3 4))
要访问向量中的元素,可以使用aref,下标从 0 开始。
提供的下标数量必须与数组的秩一致。
(aref #2A((1 2 3) (3 4 5)) 1 0) ; => 3
(aref #3A(((a b) (c d))
((e f) (g h))
((t u) (v w)))
2 0 1) ; => U
(aref #2A((1) (2)) 0) ; => ERROR (because not enough indexes provided)
另外,给出的下标必须落在创建数组时指定维度的边界之内。
可以用array-in-bounds-p来检查:
(array-in-bounds-p #2A((1) (2)) 0 0) ; => T
(array-in-bounds-p #2A((1) (2)) 2 0) ; => NIL
也可以用row-major-aref访问元素,它接受一个整数,按行主序指定元素。
(行主序下标可以通过array-row-major-index由各个下标算出来。)
(array-row-major-index #2A((1 2 3) (4 5 6)) 1 1 ) ; => 4
(row-major-aref #2A((1 2 3) (4 5 6)) 4) ; => 5
要判断一个对象是不是数组,可以用arrayp。
(arrayp #(1 2 3)) ; => T
(arrayp #2((1 2 3) (4 5 6))) ; => T
(arrayp (list 1 2 3)) ; => NIL
可以用下面这些函数获取数组的各种信息:
array-rank:获取数组的维度数(称为数组的秩)。array-dimensions:获取一个列表,其中是数组各个维度的大小。array-dimension:获取其中一个维度的大小。array-total-size:获取数组元素的总数。(let ((array #3A(((0 1) (2 3) (4 5))
((6 7) (8 9) (A B))
((C D) (E F) (G H))
((I J) (K L) (M N)))))
(list (array-rank array)
(array-dimensions array)
(array-dimension array 1)
(array-total-size array))) ; => (3 (4 3 2) 2 24)
Common Lisp 标准对数组的最大尺寸做了一些限制。 这些限制体现在几个已定义的常量中:
array-rank-limit:数组允许的最大维度数(规定不小于 8)。array-dimension-limit:任意一个维度的最大大小(规定不小于 1024)。array-total-size-limit:任意数组的最大元素数(规定不小于 1024)。