Hi,

First of all, apologies for missing the discrepancy you’re pointing out in my 
previous posting about this topic.

Secondly, the general rule is: If there is a discrepancy between ANSI CL and 
AMOP, and ANSI CL has precedence, because that’s actually the binding standard. 
The AMOP book itself stresses that the spec in its appendix is only a 
preliminary draft and not a final statement on how things should be. 
(Unfortunately, that statement isn’t included in the HTML version of the AMOP 
spec.)

> On 17 Jan 2018, at 17:53, Didier Verna <did...@lrde.epita.fr> wrote:
> 
> 
>  Hi,
> 
> In the CLHS page for ENSURE-GENERIC-FUNCTION, there is this paragraph:
> 
> "If function-name specifies a generic function that has a different
> value for the :generic-function-class argument and if the new generic
> function class is compatible[1] with the old, change-class is called to
> change the class of the generic function; otherwise an error is
> signaled.”

Unfortunately, the CLHS doesn’t specify what the default value for 
:generic-function-class is, or what happens when the user doesn’t pass a value 
for :generic-function-class.

The CLHS entry for defgeneric, however, seems to suggest that if you leave out 
the :generic-function-class option in the defgeneric macro form, and the 
already existing generic function has a class other than 
standard-generic-function, its class remains unchanged. (This I would find 
unfortunate, because it would mean that the textual form that is “in effect” 
and the actual object class can be different from each other.)

> In the AMOP however, one can read the following.
> 
> From the page on ENSURE-GENERIC-FUNCTION:
> "The behavior of this function is actually implemented by the generic
> function ensure-generic-function-using-class. When
> ensure-generic-function is called, it immediately calls
> ensure-generic-function-using-class and returns that result as its own."
> 
> And then from the page on ENSURE-GENERIC-FUNCTION-USING-CLASS:
> "If the class of the generic-function-or-nil argument is not the same as
> the class specified by the :generic-function-class argument, an error is
> signaled."
> 
> 
> Let alone the fact that this should only apply when there actually is an
> existing generic function, this seems to be in contradiction with the
> Common Lisp standard, as it would explicitly forbid changing the class
> of the generic function, even in a "compatible" way.
> 
> 
> Comments?

I don’t remember the exact details anymore why I arrived to that conclusion, 
because it’s some time ago by now, but my conclusion and strong recommendation 
is to stay away from ensure-generic-function, 
ensure-generic-funciton-using-class, and also ensure-class and 
ensure-class-using-class. My interpretation of the various specs for these is 
that they were supposed to be convenience functions for “end users”, imitating 
the effects of the corresponding macro versions, but trying to deal with too 
many corner cases at the same time which require different solutions, which is 
why they have these contradictory requirements and effects.

As far as I can tell, these functions provide nothing that can’t otherwise be 
expressed using more low-level means, including make-instance, 
initialize-instance, reinitialize-instance and change-class, which are much 
more cleanly specified and require a lot less guessing.

Both CLOS and the CLOS MOP could benefit from one or two more passes of careful 
specification fixes to make them more consistent, but I guess that’s not going 
to happen. :-(

> Footnotes: 
> [1]  BTW, what does "compatible" mean ?

Well, the AMOP essentially specifies that generic function metaobject classes 
are always only compatible with themselves.

CLOS was accepted as part of ANSI CL long before there was reasonable draft 
version of the CLOS MOP available, so some of the forward references to the 
CLOS MOP spec that were added to CLtL2 survived in ANSI CL without 
double-checking them to make them compatible again with the then-exising AMOP 
book.

My guess is that it turned out that specifying what compatibility between 
generic function metaobject classes actually means was too hard, so they 
resorted to the easy way out. ;)

Pascal

--
Pascal Costanza


Reply via email to