This section lists the differences between the [AMOP] and the CLISP implementation thereof.
Not implemented in CLISP
The generic function CLOS:MAKE-METHOD-LAMBDA is not implemented.
See Section 29.5.3.2, “Generic Function Invocation Protocol”.
Features implemented differently in CLISP
The class precedence list of CLOS:FUNCALLABLE-STANDARD-OBJECT
is different. See Section 29.2.2, “Inheritance Structure of Metaobject Classes”.
The DEFCLASS macro passes default values to CLOS:ENSURE-CLASS.
See Section 29.3.1, “Macro DEFCLASS”.
The DEFGENERIC macro passes default values to ENSURE-GENERIC-FUNCTION.
See Section 29.5.3.1, “Macro DEFGENERIC”.
The class CLOS:FORWARD-REFERENCED-CLASS is implemented differently.
See Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP.
The function CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER SIGNALs an ERROR
if the generic function has no lambda list.
Extensions specific to CLISP
The Meta-Object Protocol is applicable to classes of type STRUCTURE-CLASS.
The default superclass for STRUCTURE-CLASS instances is
STRUCTURE-OBJECT.
Structure classes do not support multiple inheritance and reinitialization.
See Section 29.3.5.1, “Initialization of class metaobjects”.
See also Section 8.2, “The structure Meta-Object Protocol”.
The DEFGENERIC macro supports user-defined options.
See User-defined options.
The class METHOD is subclassable.
See Section 29.2.2, “Inheritance Structure of Metaobject Classes”.
Slot names like NIL and T are allowed.
See Section 29.4.2.1.1, “Generic Function CLOS:SLOT-DEFINITION-NAME”.
The CLOS:VALIDATE-SUPERCLASS method is more permissive by
default and does not need to be overridden in
some “obvious” cases.
See Section 29.3.6.7, “Generic Function CLOS:VALIDATE-SUPERCLASS”.
New generic function CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS. It can sometimes
be used when overriding CLOS:DIRECT-SLOT-DEFINITION-CLASS is cumbersome.
New generic function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS. It can sometimes
be used when overriding CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS is cumbersome.
New function CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION. It
can be used in overriding methods of CLOS:COMPUTE-DISCRIMINATING-FUNCTION.
The generic function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS accepts a
:DECLARE keyword.
The functions CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS and
CLOS:STANDARD-INSTANCE-ACCESS support non-updated obsolete instances and
also support slots with allocation :CLASS.
The existence of the function CLOS:CLASS-DIRECT-SUBCLASSES
does not prevent otherwise unreferenced classes from being garbage-collected.
When CLISP encounters suspicious CLOS code, it issues a
WARNING of type CLOS:CLOS-WARNING.
To suppress the undesired warnings (not recommended!) use
EXT:SET-GLOBAL-HANDLER with MUFFLE-WARNING on the appropriate
WARNING type;.
To find where the warnings come from (recommended), set
*BREAK-ON-SIGNALS* to the appropriate WARNING type.
This is a hint that the order in which program files are loaded (order of definitions, order of macro expansions, or similar) is wrong. Example:
(defclass ware () ((title :initarg :title :accessor title)))
(defclass book (ware) ())
(defclass compact-disk (ware) ())
(defclass dvd (ware) ())
(defgeneric add-to-inventory (object))
(defmethod add-to-inventory ((object ware)) nil)
(add-to-inventory (make-instance 'book :title "CLtL1"))
(defvar *book-counter* 0)
(defmethod add-to-inventory ((object book)) (incf *book-counter*))
(add-to-inventory (make-instance 'book :title "CLtL2"))
*book-counter*
⇒ 1
Since [CLtL1] and [CLtL2] were already added to the inventory, the
programmer might have expected that *book-counter*
is 2.
A few functions, such as PRINT-OBJECT, are listed in the
[ANSI CL standard] and the [AMOP] as “standard generic functions”,
to which users may add methods.
This warning is not issued for such functions.
A generic function is defined by a contract.
Whoever puts a method on a generic function, however, is also
expecting a contract to be fulfilled.
(In the example above, it is that *book-counter*
equals the number of invocations
of add-to-inventory on book instances.)
If the generic function was already called before the
method was installed, the method's contract was definitely broken.
Maybe the programmer has foreseen this case (in this example:
he could initialize *book-counter* to the number of
instances of book that exist at this moment, rather than to 0),
or maybe not. This is what the warning is about.
This is a hint that different parts of the program, possibly developed by independent people, are colliding. Example: in addition to the code above:
(defvar *book-sales-statistics* (make-hash-table :test 'equal)) (defmethod add-to-inventory ((object book)) (setf (gethash (title object) sale-stats) (cons 0 0))) (add-to-inventory (make-instance 'book :title "AMOP")) *book-counter* ⇒1*book-sales-statistics* ⇒#S(HASH-TABLE :TEST FASTHASH-EQUAL ("AMOP" . (0 . 0)))
The programmer who programmed the first
method expects that add-to-inventory@book*book-counter* will be incremented.
The programmer who programmed the second
method expects that add-to-inventory@book*book-sales-statistics* gets
augmented. If the implementation gives no warning, one of the two
programmers will waste time debugging.
This warning can be warranted for the same reason as above: if the old method and the new method have a different contract, something is fishy and possibly wrong. Additionally, the programmers may not even have intended to replace the method. They may have intended cumulative effects of the two methods.
| These notes document CLISP version 2.49 | Last modified: 2010-07-07 |