Search code examples
macroscommon-lispaccessorclos

What is a didatic example of the with-slots macro in CLOS?


The Common Lisp HyperSpec covers the with-slots macro. However, the example is hard to grasp.

Is there an easier and more didactic example about it?


Solution

  • To better understand with-slots, one should look into defclass first.

    No reader or writer functions are defined by default; their generation must be explicitly requested. However, slots can always be accessed using slot-value.

    It means that, unless specific request, defclass don't create any accessor for the slots:

    > (defclass point ()
      (x y))
    
    (let ((new-point (make-instance 'point)))
      (setf (point-x new-point) 1))
    
    Error: The function (COMMON-LISP:SETF COMMON-LISP-USER::POINT-X) is undefined.
    

    In this case, one must use the slot-value function to access or modify the slot value.

    (defclass point ()
      (x y))
    
    (let ((new-point (make-instance 'point)))
      (setf (slot-value new-point 'x) 1))
    

    Obviously, when there are several slots to update, the code become a little cumbersome:

    (defmethod translate ((point-instance point) delta-x delta-y)
      (setf (slot-value point-instance 'x)
            (+ (slot-value point-instance 'x) delta-x))
      (setf (slot-value point-instance 'y)
            (+ (slot-value point-instance 'y) delta-y)))
    

    For that reason, the with-slots macro can make the code easier to read:

    (defmethod translate ((point-instance point) delta-x delta-y)
      (with-slots (x y) point-instance
        (setf x (+ x delta-x))
        (setf y (+ y delta-y))))