CLOS:使用插槽值初始化另一个插槽

JNe*_*ens 3 lisp common-lisp clos

我很擅长使用CLOS.在这里,我写了一种使用CLOS定义队列的可能方法:

(defclass Queue ()
    ((queue-size
        :reader queue-size
        :initarg :queue-size
        :initform (error "Provide a queue-size when initialising a Queue")
        :type number)
    (elements
        :accessor elements
        :initform (make-array queue-size :initial-element nil))
    (put-ptr
        :accessor put-ptr
        :initform 0
        :type number)
    (get-ptr
        :accessor get-ptr
        :initform 0
        :type number)))
Run Code Online (Sandbox Code Playgroud)

如您所见,我使用插槽的值在插槽queue-size中创建数组elements.但是,不幸的是,这给了我以下错误:

*** - DEFAULT-ELEMENTS: variable QUEUE-SIZE has no value
Run Code Online (Sandbox Code Playgroud)

正如我所说,我对CLOS很新.有什么办法我还能这样做吗?是否可以覆盖某种init方法?如果是,我该怎么做?

Rai*_*wig 8

在CLOS中,您不能直接将插槽称为变量.此外,您无法在initforms引用该对象的其他插槽.

这个例子简化了:

CL-USER 27 > (defclass queue () (size elements))
#<STANDARD-CLASS QUEUE 4020001AB3>

CL-USER 28 > (describe (make-instance 'queue))

#<QUEUE 40200040CB> is a QUEUE
SIZE          #<unbound slot>
ELEMENTS      #<unbound slot>
Run Code Online (Sandbox Code Playgroud)

我们现在设置elements插槽:

CL-USER 36 > (defclass queue () ((size :initarg :size) elements))
#<STANDARD-CLASS QUEUE 42E0A2DBFB>
Run Code Online (Sandbox Code Playgroud)

为此,我们编写了一个initialize-instance :after方法.通常初始化发生,之后我们的方法运行.WITH-SLOTS允许我们在代码中使用像变量这样的特定插槽.在这里我们访问插槽sizeelements:

CL-USER 37 > (defmethod initialize-instance :after ((q queue) &rest initargs)
               (with-slots (size elements) q
                 (setf elements (make-array size :initial-element nil))))
#<STANDARD-METHOD INITIALIZE-INSTANCE (:AFTER) (QUEUE) 402000ADD3>
Run Code Online (Sandbox Code Playgroud)

没有 WITH-SLOTS,使用该函数 SLOT-VALUE,它看起来像这样:

CL-USER 38 > (defmethod initialize-instance :after ((q queue) &rest initargs)
               (setf (slot-value q 'elements)
                     (make-array (slot-value q 'size) :initial-element nil)))
Run Code Online (Sandbox Code Playgroud)

例:

CL-USER 39 > (describe (make-instance 'queue :size 10))

#<QUEUE 402000BE0B> is a QUEUE
SIZE          10
ELEMENTS      #(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
Run Code Online (Sandbox Code Playgroud)