2015-02-23 6 views
1

Я пытаюсь создать объект узла в Common Lisp, используя SBCL, который инициализируется его текстовым элементом, а затем имеет ссылки на другие узлы. Предполагается, что моя функциональная ссылка займет узел «from_node», получит его членские ссылки (которые должны быть изменяемым/расширяемым вектором) и нажмите на узел «to_node».Почему этот lisp-вектор не распространяется?

Скомпилировать 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] 

Первоначально я думал, что я делал неизменный вектор, но «: регулируемый т» должен позволить этому работать.

Что не так?

ответ

3

VECTOR-PUSH-EXTEND требует, чтобы векторный аргумент был «вектором с указателем заполнения». Передача : настраивается 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) 

Это важное различие, потому что вы можете иметь регулируемые массивы без заполнения указателей, как вы уже видели. Они могут быть изменены, но всегда имеют столько элементов, сколько места. (Например, в первом случае, * х * имеет длина один. Вы также можете иметь массивы заполнят указатели, которые не являются регулируемыми. Это будет по-прежнему позволяют использовать вектор-толчок и вектор-пуш простирайтесь до тех пор, пока они не будут заполнены, но после этого не могут быть изменены.

+0

Спасибо, функция не имела «следующего положения для заполнения», – SlightlyCyborg

Смежные вопросы