Skip to main content

slot-unbound

slot-unbound Standard Generic Function

Syntax:

slot-unbound class instance slot-name → {result}*

Method Signatures:

slot-unbound (class t) instance slot-name

Arguments and Values:

class—the class of the instance.

instance—the instance in which an attempt was made to read the unbound slot.

slot-name—the name of the unbound slot.

result—an object.

Description:

The generic function slot-unbound is called when an unbound slot is read in an instance whose metaclass is standard-class. The default method signals an error of type unbound-slot. The name slot of the unbound-slot condition is initialized to the name of the offending variable, and the instance slot of the unbound-slot condition is initialized to the offending instance.

The generic function slot-unbound is not intended to be called by programmers. Programmers may write methods for it. The function slot-unbound is called only indirectly by slot-value.

If slot-unbound returns, only the primary value will be used by the caller, and all other values will be ignored.

Exceptional Situations:

The default method on slot-unbound signals an error of type unbound-slot.

See Also:

slot-makunbound

Notes:

An unbound slot may occur if no :initform form was specified for the slot and the slot value has not been set, or if slot-makunbound has been called on the slot.

Expanded Reference: slot-unbound

Default Behavior

slot-unbound is called by slot-value when an unbound slot is read. The default method signals an unbound-slot error.

(defclass item ()
((value :initarg :value)))

(let ((obj (make-instance 'item)))
(handler-case (slot-value obj 'value)
(unbound-slot (c)
(format nil "Unbound: ~A" (cell-error-name c)))))
=> "Unbound: VALUE"

Providing a Default Value for Unbound Slots

You can define a method on slot-unbound to return a default value instead of signaling an error. This implements lazy initialization.

(defclass lazy-default ()
((data :initarg :data :accessor lazy-data)))

(defmethod slot-unbound ((class t) (instance lazy-default) slot-name)
(if (eq slot-name 'data)
(setf (lazy-data instance) (list :default))
(call-next-method)))

(let ((obj (make-instance 'lazy-default)))
;; First access triggers slot-unbound, which initializes the slot
(lazy-data obj))
=> (:DEFAULT)

Lazy Initialization Pattern

slot-unbound is particularly useful for expensive computations that should only happen on first access.

(defclass expensive-resource ()
((connection :accessor resource-connection)))

(defmethod slot-unbound ((class t) (obj expensive-resource)
(slot-name (eql 'connection)))
;; Simulate creating an expensive resource on first access
(setf (resource-connection obj) (cons :connection (get-universal-time))))

(let ((r (make-instance 'expensive-resource)))
(consp (resource-connection r)))
=> T