Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CLOS: Use a slot value to initialize another slot

I am pretty new to using CLOS. Here, I wrote one possible way of defining a Queue using 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)))

As you can see, I use the value of the slot queue-size to make the array in the slot elements. But, unfortunately, this gives me the following error:

*** - DEFAULT-ELEMENTS: variable QUEUE-SIZE has no value

As I said, I am pretty new to CLOS. Is there any way I can still do this? Is it possible to overwrite some kind of init method? If yes, how do I do this?

like image 446
JNevens Avatar asked Dec 17 '25 20:12

JNevens


1 Answers

In CLOS you can't directly refer to slots as variables. Also you can't refer to to other slots of the object in initforms.

The example, simplified:

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>

We'll now set the elements slot:

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

For that we write a initialize-instance :after method. The usual initializing happens and after that our method runs. WITH-SLOTS allows us to use certain slots like variables in our code. Here we access the slots size and elements:

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>

Without the macro WITH-SLOTS, using the function SLOT-VALUE, it looks like this:

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)))

Example:

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)
like image 54
Rainer Joswig Avatar answered Dec 21 '25 00:12

Rainer Joswig