5

所以我再次经历了 Practical Common Lisp,我无法真正理解如何创建一个具有恒定大小的向量。

根据书:

然而,即使是带有填充指针的向量也不能完全调整大小。向量 *x* 最多可以包含五个元素。要制作任意大小的向量,您需要传递 MAKE-ARRAY 另一个关键字参数::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?创建非动态(不可调整)数组的正确方法是什么?

4

2 回答 2

6

该行为是特定于实现的。

Common Lisp 规范说:

没有指定的方法来创建可调整数组 p 肯定返回 false 的数组。

一个实现可以使向量可调,即使 的:adjustable参数make-array被给出为nil

要查看一个数组对象是否真的可以调整,需要调用adjustable-array-p.

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

所以:adjustable nilarg 只是告诉 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 中是可调整的,即使:adjustablearg 给出为nil

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

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

于 2019-08-22T07:25:40.063 回答
6

的规范make-array说它是依赖于实现的数组:adjustable nil是否实际上是可调整的。在注释中,它继续说:

没有指定的方法来创建可调整数组 p 肯定返回 false 的数组。

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

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

于 2019-08-22T07:25:53.110 回答