SBCL supports a metaobject protocol which is intended to be compatible with AMOP; present exceptions to this (as distinct from current bugs) are:
compute-effective-method
only returns one value, not two.
There is no record of what the second return value was meant to indicate, and apparently no clients for it.
sb-mop:funcallable-standard-object
are
(function standard-object)
, not (standard-object function)
.
This is to ensure that the standard-object
class is the last of
the standardized classes before t
appearing in the class
precedence list of generic-function
and
standard-generic-function
, as required by section 1.4.4.5 of the
ANSI specification.
:declare
and :declarations
to
ensure-generic-function
are both accepted, with the leftmost
argument defining the declarations to be stored and returned by
generic-function-declarations
.
Where AMOP specifies :declarations
as the keyword argument to
ensure-generic-function
, the Common Lisp standard specifies
:declare
. Portable code should use :declare
.
validate-superclass
should treat standard-class
and
funcallable-standard-class
as compatible metaclasses, we
impose an additional requirement at class finalization time: a class
of metaclass funcallable-standard-class
must have
function
in its superclasses, and a class of metaclass
standard-class
must not.
After a class has been finalized, it is associated with a class
prototype which is accessible by a standard mop function
sb-mop:class-prototype
. The user can then ask whether this
object is a function
or not in several different ways: whether it
is a function according to typep
; whether its class-of
is
subtypep
function
, or whether function
appears in
the superclasses of the class. The additional consistency requirement
comes from the desire to make all of these answers the same.
The following class definitions are bad, and will lead to errors either immediately or if an instance is created:
(defclass bad-object (funcallable-standard-object) () (:metaclass standard-class))
(defclass bad-funcallable-object (standard-object) () (:metaclass funcallable-standard-class))
The following definition is acceptable:
(defclass mixin () ((slot :initarg slot))) (defclass funcallable-object (funcallable-standard-object mixin) () (:metaclass funcallable-standard-class))
and leads to a class whose instances are funcallable and have one slot.
Note that this requirement also applies to the class
sb-mop:funcallable-standard-object
, which has metaclass
sb-mop:funcallable-standard-class
rather than
standard-class
as AMOP specifies.
common-lisp-user
package or exported by any package defined in
the ANSI Common Lisp standard.” is interpreted to mean that the
standardized classes themselves should not have slots named by external
symbols of public packages.
The rationale behind the restriction is likely to be similar to the ANSI Common Lisp restriction on defining functions, variables and types named by symbols in the Common Lisp package: preventing two independent pieces of software from colliding with each other.
new-value
argument to (setf
sb-mop:slot-value-using-class)
are not allowed: all user-defined
methods must have a specializer of the class t
.
This prohibition is motivated by a separation of layers: the
slot-value-using-class
family of functions is intended for use in
implementing different and new slot allocation strategies, rather than
in performing application-level dispatching. Additionally, with this
requirement, there is a one-to-one mapping between metaclass, class and
slot-definition-class tuples and effective methods of (setf
slot-value-using-class)
, which permits optimization of (setf
slot-value-using-class)
's discriminating function in the same manner as
for slot-value-using-class
and slot-boundp-using-class
.
Note that application code may specialize on the new-value
argument of slot accessors.
name
argument to ensure-class
, if
any, is only redefined if it is the proper name of that class;
otherwise, a new class is created.
This is consistent with the description of ensure-class
in AMOP
as the functional version of defclass
, which has this behaviour;
however, it is not consistent with the weaker requirement in AMOP, which
states that any class found by find-class
, no matter what its
class-name
, is redefined.
In addition, SBCL supports extensions to the Metaobject protocol from AMOP; at present, they are:
defmethod
forms is provided by the
make-method-specializers-form
function, which returns a form
which, when evaluated in the lexical environment of the
defmethod
, returns a list of specializer metaobjects. This
operator suffers from similar restrictions to those affecting
make-method-lambda
, namely that the generic function must be
defined when the defmethod
form is expanded, so that the
correct method of make-method-specializers-form
is invoked.
The system-provided method on make-method-specializers-form
generates a call to find-class
for each symbol specializer
name, and a call to intern-eql-specializer
for each (eql
x)
specializer name.
find-method
, is provided by
parse-specializer-using-class
and
unparse-specializer-using-class
, which dispatch on their first
argument, the generic function associated with a method with the given
specializer. The system-provided methods on those methods convert
between classes and proper names and between lists of the form
(eql
x)
and interned eql specializer objects.