Structures

Structures are faster and simpler than CLOS classes (fixed slots, single inheritance, compiled accessors), but redefining a structure at the REPL is less graceful. Use CLOS classes (Module 30) when you need flexibility or multiple inheritance.

(defstruct point
  (x 0 :type real)
  (y 0 :type real))

;; defstruct generates: make-point, point-p, point-x, point-y, copy-point, and setf accessors
(defparameter *p* (make-point :x 3 :y 4))
(point-x *p*)                         ; 3
(setf (point-y *p*) 10)
(point-p *p*)                         ; T
*p*                                   ; #S(POINT :X 3 :Y 10)
(copy-point *p*)
(equalp (make-point :x 1) (make-point :x 1))   ; T

;; Options: custom constructors, inheritance, read-only slots, printing
(defstruct (point3d (:include point)  ; single inheritance
                    (:constructor new-point3d (x y z)))   ; positional constructor (BOA constructor)
  (z 0 :type real))
(point-x (new-point3d 1 2 3))         ; 1: inherited accessor works

(defstruct (account (:conc-name acc-))    ; accessor prefix: acc-owner, acc-balance
  (owner "" :type string :read-only t)
  (balance 0))

(defstruct (node (:print-function (lambda (n stream depth)
                                    (declare (ignore depth))
                                    (format stream "#<NODE ~a>" (node-value n)))))
  value next)