为什么这个 lisp 向量没有扩展?

Why is this lisp vector not extending?

我正在尝试使用 SBCL 在 Common Lisp 中创建一个节点对象,该 SBCL 使用其文本元素进行初始化,然后 links 到其他节点。我的函数 link 应该获取节点 "from_node",获取其成员 links(应该是一个 mutable/extendable 向量)并推入节点 "to_node"。

我编译 say.lisp,创建 2 个代表节点的全局变量,然后尝试 link 这两个节点。我收到一个错误

这里是say.lisp

(defclass node ()
  ((text
     :initarg :text)
   (links
     :initform (make-array 1 :adjustable t))))

(defun link (from_node to_node)
  (vector-push-extend to_node (slot-value from_node 'links)))

然后在 REPL

* (load "say.lisp")  
T
* (defvar *x* (make-instance 'node :text "hello world"))

*X*
* (defvar *y* (make-instance 'node :text "bye world"))  

*Y*
* (link *x* *y*)

debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {1003016593}>:
  The value #() is not of type (AND VECTOR (NOT SIMPLE-ARRAY)).

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(VECTOR-PUSH-EXTEND #<NODE {10031D3983}> #() NIL)
0] 

最初我认为我正在制作一个不可变向量,但“:adjustable t”应该允许它工作。

怎么了?

VECTOR-PUSH-EXTEND 要求向量参数是 "vector with a fill pointer." 将 :adjustable t 传递给 make-array 使其可调整,但不给它一个填充指针。例如,没有填充指针:

CL-USER> (defparameter *x* (make-array 1 :adjustable t))
*X*
CL-USER> *x*
#(0)
CL-USER> (vector-push-extend 3 *x*)
; Evaluation aborted on #<SIMPLE-TYPE-ERROR expected-type:
                    (AND VECTOR (SATISFIES ARRAY-HAS-FILL-POINTER-P))
                    datum: #<(VECTOR T 1) {100464C57F}>>.

带填充指针:

CL-USER> (defparameter *x* (make-array 1 :adjustable t :fill-pointer 0))
*X*
CL-USER> *x*
#()
CL-USER> (vector-push-extend 3 *x*)
0
CL-USER> (vector-push-extend 4 *x*)
1
CL-USER> (vector-push-extend 5 *x*)
2
CL-USER> *x*
#(3 4 5)

这是一个重要的区别,因为如您所见,您可以拥有不带填充指针的可调整数组。这些可以调整大小,但总是显示有多少元素就有多少space。 (例如,在第一种情况下,*x*length 一个。你也可以让数组填充不可调整的指针。这些将仍然允许您使用 vector-pushvector-push-extend 直到它们被填满,但之后无法调整大小。