为什么这个 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-push 和 vector-push-extend 直到它们被填满,但之后无法调整大小。
我正在尝试使用 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-push 和 vector-push-extend 直到它们被填满,但之后无法调整大小。