如何保护矢量不调整大小?

How to protect vector from resizing?

所以我再次学习 Practical Common Lisp,但我无法真正理解如何创建具有恒定大小的向量。

据书:

However, even a vector with a fill pointer isn't completely resizable. The vector *x* can hold at most five elements. To make an arbitrarily resizable vector, you need to pass MAKE-ARRAY another keyword argument: :adjustable.

然而,当我使用 (vector-push-extend) 时,即使我设置 :adjustable nil(或保留默认值),我也可以扩展我的初始向量。

(vector-push 'a *x*) ;; 0
(vector-push 'b *x*) ;; 1
(vector-push 'c *x*) ;; 2
(vector-push 'd *x*) ;; 3
(vector-push 'e *x*) ;; 4
*x* ;; #(A B C D E)
(vector-push 'f *x*) ;; NIL
*x* ;; #(A B C D E)
(vector-push-extend 'f *x*) ;; 5
*x* ;; #(A B C D E F)

我假设 (vector-push-extend) 不能调整不是 :adjustable 的数组的大小?创建非动态(不可调整)数组的正确方法是什么?

该行为是特定于实现的。

Common Lisp 规范说:

There is no specified way to create an array for which adjustable-array-p definitely returns false.

即使 make-array:adjustable 参数以 nil.

形式给出,实现也可能使向量可调

要查看数组对象是否实际上可调,需要调用adjustable-array-p.

Common Lisp 标准说向量是明确可调的(因此如果被要求的话也是实际可调的。如果不是请求,矢量仍然可以可调实际可调

所以 :adjustable nil arg 只是告诉 Lisp,如果可能的话,它可以使向量不可调整。

在 SBCL 中:

1)法向量不可调整:

* (make-array 5)
#(0 0 0 0 0)
* (adjustable-array-p *)
NIL

2) 带有填充指针的向量在 SBCL 中实际上是可调整的

* (make-array 5 :fill-pointer 0)
#()
* (adjustable-array-p *)
T

3) 带有填充指针的向量在 SBCL 中 实际上是可调整的,即使 :adjustable arg 被指定为 nil

* (make-array 5 :fill-pointer 0 :adjustable nil)
#()
* (adjustable-array-p *)
T

那是在 SBCL 中。在 LispWorks 中,2) 和 3) 实际上是不可调整的。

make-array 的规范表明,具有 :adjustable nil 的数组是否 实际上是可调整的 取决于实现。在注释中,它继续说:

There is no specified way to create an array for which adjustable-array-p definitely returns false.

所以,这真的取决于实施。

如果不想扩展,正确的方法是使用vector-push