29.10. Slot Access

29.10.1. Instance Structure Protocol
29.10.2. Funcallable Instances
29.10.3. Customization
29.10.3.1. Function CLOS:STANDARD-INSTANCE-ACCESS
29.10.3.2. Function CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS
29.10.3.3. Function CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION
29.10.3.4. Generic Function CLOS:SLOT-VALUE-USING-CLASS
29.10.3.5. Generic Function (SETF CLOS:SLOT-VALUE-USING-CLASS)
29.10.3.6. Generic Function CLOS:SLOT-BOUNDP-USING-CLASS
29.10.3.7. Generic Function CLOS:SLOT-MAKUNBOUND-USING-CLASS

29.10.1. Instance Structure Protocol

The instance structure protocol is responsible for implementing the behavior of the slot access functions like SLOT-VALUE and (SETF SLOT-VALUE).

For each CLOS slot access function other than SLOT-EXISTS-P, there is a corresponding generic function which actually provides the behavior of the function. When called, the slot access function finds the pertinent effective slot definition metaobject, calls the corresponding generic function and returns its result. The arguments passed on to the generic function include one additional value, the class of the object argument, which always immediately precedes the object argument.

Table 29.6. The correspondence between slot access function and underlying slot access generic function

Slot Access FunctionCorresponding Slot Access Generic Function
SLOT-VALUE object slot-nameCLOS:SLOT-VALUE-USING-CLASS class object slot
(SETF SLOT-VALUE) new-value object slot-name(SETF CLOS:SLOT-VALUE-USING-CLASS) new-value class object slot
SLOT-BOUNDP object slot-nameCLOS:SLOT-BOUNDP-USING-CLASS class object slot
SLOT-MAKUNBOUND object slot-nameCLOS:SLOT-MAKUNBOUND-USING-CLASS class object slot

At the lowest level, the instance structure protocol provides only limited mechanisms for portable programs to control the implementation of instances and to directly access the storage associated with instances without going through the indirection of slot access. This is done to allow portable programs to perform certain commonly requested slot access optimizations.

In particular, portable programs can control the implementation of, and obtain direct access to, slots with allocation :INSTANCE and type T. These are called directly accessible slots .

The relevant specified around-method on CLOS:COMPUTE-SLOTS determines the implementation of instances by deciding how each slot in the instance will be stored. For each directly accessible slot, this method allocates a location and associates it with the effective slot definition metaobject. The location can be accessed by calling the CLOS:SLOT-DEFINITION-LOCATION generic function. Locations are non-negative integers. For a given class, the locations increase consecutively, in the order that the directly accessible slots appear in the list of effective slots. (Note that here, the next paragraph, and the specification of this around-method are the only places where the value returned by CLOS:COMPUTE-SLOTS is described as a list rather than a set.)

Given the location of a directly accessible slot, the value of that slot in an instance can be accessed with the appropriate accessor. For STANDARD-CLASS, this accessor is the function CLOS:STANDARD-INSTANCE-ACCESS. For CLOS:FUNCALLABLE-STANDARD-CLASS, this accessor is the function CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS. In each case, the arguments to the accessor are the instance and the slot location, in that order. See the definition of each accessor for additional restrictions on the use of these function.

Portable programs are permitted to affect and rely on the allocation of locations only in the following limited way: By first defining a portable primary method on CLOS:COMPUTE-SLOTS which orders the returned value in a predictable way, and then relying on the defined behavior of the specified around-method to assign locations to all directly accessible slots. Portable programs may compile-in calls to low-level accessors which take advantage of the resulting predictable allocation of slot locations.

This example shows the use of this mechanism to implement a new class metaobject class, ordered-class and class option :SLOT-ORDER. This option provides control over the allocation of slot locations. In this simple example implementation, the :SLOT-ORDER option is not inherited by subclasses; it controls only instances of the class itself.

(defclass ordered-class (standard-class)
  ((slot-order :initform ()
               :initarg :slot-order
               :reader class-slot-order)))

(defmethod compute-slots ((class ordered-class))
  (let ((order (class-slot-order class)))
    (sort (copy-list (call-next-method))
          #'(lambda (a b)
              (< (position (slot-definition-name a) order)
                 (position (slot-definition-name a) order))))))

Following is the source code the user of this extension would write. Note that because the code above does not implement inheritance of the :SLOT-ORDER option, the function distance must not be called on instances of subclasses of point; it can only be called on instances of point itself.

(defclass point ()
  ((x :initform 0)
   (y :initform 0))
  (:metaclass ordered-class)
  (:slot-order x y))

(defun distance (point)
  (sqrt (/ (+ (expt (standard-instance-access point 0) 2)
              (expt (standard-instance-access point 1) 2))
           2.0)))

Implementation dependent: only in CLISP

You cannot assume that the slot-location values start at 0. In class point, for example, x and y will be at slot locations 1 and 2, not 0 and 1.

In more realistic uses of this mechanism, the calls to the low-level instance structure accessors would not actually appear textually in the source program, but rather would be generated by a meta-level analysis program run during the process of compiling the source program.

29.10.2. Funcallable Instances

Instances of classes which are themselves instances of CLOS:FUNCALLABLE-STANDARD-CLASS or one of its subclasses are called funcallable instances. Funcallable instances can only be created by ALLOCATE-INSTANCE (CLOS:FUNCALLABLE-STANDARD-CLASS).

Like standard instances, funcallable instances have slots with the normal behavior. They differ from standard instances in that they can be used as functions as well; that is, they can be passed to FUNCALL and APPLY, and they can be stored as the definition of a function name. Associated with each funcallable instance is the function which it runs when it is called. This function can be changed with CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION.

The following simple example shows the use of funcallable instances to create a simple, DEFSTRUCT-like facility. (Funcallable instances are useful when a program needs to construct and maintain a set of functions and information about those functions. They make it possible to maintain both as the same object rather than two separate objects linked, for example, by hash tables.)

(defclass constructor ()
  ((name :initarg :name :accessor constructor-name)
   (fields :initarg :fields :accessor constructor-fields))
  (:metaclass funcallable-standard-class))
⇒ #>FUNCALLABLE-STANDARD-CLASS CONSTRUCTOR>
(defmethod initialize-instance :after ((c constructor) &KEY)
  (with-slots (name fields) c
    (set-funcallable-instance-function
      c
      #'(lambda ()
          (let ((new (make-array (1+ (length fields)))))
            (setf (aref new 0) name)
            new)))))
⇒ #<STANDARD-METHOD :AFTER (#<FUNCALLABLE-STANDARD-CLASS CONSTRUCTOR>)>
(setq c1 (make-instance 'constructor :name 'position :fields '(x y)))
⇒ #<CONSTRUCTOR #<UNBOUND>>
(setq p1 (funcall c1))
⇒ #(POSITION NIL NIL)

29.10.3. Customization

29.10.3.1. Function CLOS:STANDARD-INSTANCE-ACCESS

Syntax
(CLOS:STANDARD-INSTANCE-ACCESS instance location)
Arguments
instance
an object.
location
a slot location
Value
an object.
Purpose

This function is called to provide direct access to a slot in an instance. By usurping the normal slot lookup protocol, this function is intended to provide highly optimized access to the slots associated with an instance.

The following restrictions apply to the use of this function:

  • The instance argument must be a standard instance (it must have been returned by ALLOCATE-INSTANCE(STANDARD-CLASS)).
  • The instance argument cannot be an non-updated obsolete instance.
  • The location argument must be a location of one of the directly accessible slots of the instance's class.
  • The slot must be bound.

The results are undefined if any of these restrictions are violated.

Implementation dependent: only in CLISP

The second and third restrictions do not apply in CLISP. CLISP's implementation supports non-updated obsolete instances and also supports slots with allocation :CLASS.

Syntax
(CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS instance location)
Arguments
instance
an object.
location
a slot location
Value
an object.
Purpose

This function is called to provide direct access to a slot in an instance. By usurping the normal slot lookup protocol, this function is intended to provide highly optimized access to the slots associated with an instance.

The following restrictions apply to the use of this function:

  • The instance argument must be a funcallable instance (it must have been returned by ALLOCATE-INSTANCE (CLOS:FUNCALLABLE-STANDARD-CLASS)).
  • The instance argument cannot be an non-updated obsolete instance.
  • The location argument must be a location of one of the directly accessible slots of the instance's class.
  • The slot must be bound.

The results are undefined if any of these restrictions are violated.

Implementation dependent: only in CLISP

The second and third restrictions do not apply in CLISP. CLISP's implementation supports non-updated obsolete instances and also supports slots with allocation :CLASS.

Syntax
(CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION funcallable-instance function)
Arguments
funcallable-instance
a funcallable instance (it must have been returned by ALLOCATE-INSTANCE (CLOS:FUNCALLABLE-STANDARD-CLASS)).
function
A function.
Values
The values returned by this generic function are unspecified.
Purpose
This function is called to set or to change the function of a funcallable instance. After CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION is called, any subsequent calls to funcallable-instance will run the new function.

29.10.3.4. Generic Function CLOS:SLOT-VALUE-USING-CLASS

Syntax
(CLOS:SLOT-VALUE-USING-CLASS class object slot)
Arguments
class
a class metaobject - the class of the object argument.
object
an object.
slot
an effective slot definition metaobject.
Values
an object.
Purpose

This generic function implements the behavior of the SLOT-VALUE function. It is called by SLOT-VALUE with the class of object as its first argument and the pertinent effective slot definition metaobject as its third argument.

The generic function CLOS:SLOT-VALUE-USING-CLASS returns the value contained in the given slot of the given object. If the slot is unbound, SLOT-UNBOUND is called.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

(CLOS:SLOT-VALUE-USING-CLASS (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
(CLOS:SLOT-VALUE-USING-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

(CLOS:SLOT-VALUE-USING-CLASS (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.

29.10.3.5. Generic Function (SETF CLOS:SLOT-VALUE-USING-CLASS)

Syntax
((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value class object slot)
Arguments
new-value
an object.
class
a class metaobject - the class of the object argument.
object
an object.
slot
an effective slot definition metaobject.
Value
The new-value argument.
Purpose

The generic function (SETF CLOS:SLOT-VALUE-USING-CLASS) implements the behavior of the (SETF SLOT-VALUE) function. It is called by (SETF SLOT-VALUE) with the class of object as its second argument and the pertinent effective slot definition metaobject as its fourth argument.

The generic function (SETF CLOS:SLOT-VALUE-USING-CLASS) sets the value contained in the given slot of the given object to the given new value; any previous value is lost.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.

29.10.3.6. Generic Function CLOS:SLOT-BOUNDP-USING-CLASS

Syntax
(CLOS:SLOT-BOUNDP-USING-CLASS class object slot)
Arguments
class
a class metaobject - the class of the object argument.
object
an object.
slot
an effective slot definition metaobject.
Value
BOOLEAN
Purpose

This generic function implements the behavior of the SLOT-BOUNDP function. It is called by SLOT-BOUNDP with the class of object as its first argument and the pertinent effective slot definition metaobject as its third argument.

The generic function CLOS:SLOT-BOUNDP-USING-CLASS tests whether a specific slot in an instance is bound.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

(CLOS:SLOT-BOUNDP-USING-CLASS (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
(CLOS:SLOT-BOUNDP-USING-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

(CLOS:SLOT-BOUNDP-USING-CLASS (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.

Remarks. In cases where the class metaobject class does not distinguish unbound slots, true should be returned.

29.10.3.7. Generic Function CLOS:SLOT-MAKUNBOUND-USING-CLASS

Syntax
(CLOS:SLOT-MAKUNBOUND-USING-CLASS class object slot)
Arguments
class
a class metaobject - the class of the object argument.
object
an object.
slot
an effective slot definition metaobject.
Value
The object argument.
Purpose

This generic function implements the behavior of the SLOT-MAKUNBOUND function. It is called by SLOT-MAKUNBOUND with the class of object as its first argument and the pertinent effective slot definition metaobject as its third argument.

The generic function CLOS:SLOT-MAKUNBOUND-USING-CLASS restores a slot in an object to its unbound state. The interpretation of restoring a slot to its unbound state depends on the class metaobject class.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

(CLOS:SLOT-MAKUNBOUND-USING-CLASS (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
(CLOS:SLOT-MAKUNBOUND-USING-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

(CLOS:SLOT-MAKUNBOUND-USING-CLASS (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.

These notes document CLISP version 2.49Last modified: 2010-07-07