为什么这个lisp向量不会扩展?

时间:2015-02-23 17:49:28

标签: vector common-lisp sbcl

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

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

这是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] 

最初我以为我正在制作一个不可变的向量,但是“:可调整的t”应该可以让它工作。

有什么问题?

1 个答案:

答案 0 :(得分:3)

VECTOR-PUSH-EXTEND要求vector参数是“带有填充指针的向量”。将:可调整传递给 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)

这是一个重要的区别,因为你可以拥有没有填充指针的可调节数组,如你所见。这些可以调整大小,但总是看起来与空间一样多。 (例如,在第一种情况下, * x * 具有长度一。您还可以使用数组填充不可调整的指针。这些仍然允许您使用< strong> vector-push 和 vector-push-extend ,直到它们被填满,但之后无法调整大小。