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
SIGNAL
s 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-WARNING
This 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-WARNING
This 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
ware
s, book
s etc
created so far, i.e., their components will become inaccessible.
STYLE-WARNING
This 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 |