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.
It is not possible to create a class with metaclass
STANDARD-CLASS when specifying a superclass with metaclass
CLOS:FUNCALLABLE-STANDARD-CLASS, even though CLOS:VALIDATE-SUPERCLASS
returns T for this situation.
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 or suboptimal CLOS code,
it issues a WARNING of type CLOS:CLOS-WARNING
or a STYLE-WARNING of type CLOS:CLOS-STYLE-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) may be 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.
STYLE-WARNINGThis warning is actually a STYLE-WARNING because it indicates the
behavior officially sanctioned by the standard and useful in some situations.
We only warn on it because it may lead to confusing
behavior for inexperienced users.
A generic function is defined by a contract.
Whoever adds a method to a generic function, however, also
expects the contract to be fulfilled.
(In the example above, the contract is that
*book-counter* equals the number of invocations
of add-to-inventory on
book instances.)
If the generic function has already been called before the
method was added, the method's contract is 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.
If your generic function constitutes a public interface which is
used by adding methods (similar to aforementioned PRINT-OBJECT), you
can declare it as such:
(defgeneric my-public-gf (a b c) (declare (clos:dynamically-modifiable)) ...)
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.
STYLE-WARNINGThis warning is actually a STYLE-WARNING because it indicates the
behavior officially sanctioned by the standard and useful in some situations.
We only warn on it because it may lead to confusing
behavior for inexperienced users.
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.
This is a hint that different parts of the program define the same
CLASS incompatibly, and some objects, created to the old
specification, have been obsoleted by the new one.
Example: in addition to the code
above:
(defclass ware () ((title :initarg :title :accessor title) (year :initarg :year :accessor year)))
Evaluating the above will obsolete all objects of type
wares, books etc
created so far, i.e., their components will become inaccessible.
STYLE-WARNINGThis warning is actually a STYLE-WARNING because it indicates the
behavior officially sanctioned by the standard and useful in some situations.
We only warn on it because it may lead to confusing
behavior for inexperienced users.
In addition to the above, this warning tells the programmers that they are losing some objects they have already created.
| These notes document CLISP version 2.49.93+ | Last modified: 2018-02-19 |