From: Christopher R. Barry
Subject: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <87emexad97.fsf@2xtreme.net>
This is driving me insane. If I have a method that has an (EQL <object>)
specializer, how do I call FIND-METHOD on it? Example:

  USER(29): (defmethod my-object-is-easy-to-get ((int integer) some-object)
	      'blah)
  #<STANDARD-METHOD MY-OBJECT-IS-EASY-TO-GET (INTEGER T)>

  USER(30): (find-method #'my-object-is-easy-to-get nil
			 (mapcar #'find-class '(integer t)))
  #<STANDARD-METHOD MY-OBJECT-IS-EASY-TO-GET (INTEGER T)>

Now with an EQL-specializer:

  USER(38): (defconstant +magic-number+ #xDEADBEEF)
  +MAGIC-NUMBER+

  USER(39): (defmethod my-object-is-impossible-to-get ((n (eql +magic-number+))
						       some-object)
	      'blah)
  #<STANDARD-METHOD MY-OBJECT-IS-IMPOSSIBLE-TO-GET ((EQL 3735928559) T)>

And two slightly different attempts at getting the object:

  USER(41): (find-method #'my-object-is-impossible-to-get nil
			 `((eql ,+magic-number+) ,(find-class 't)))
  Error: The generic function
	 #<STANDARD-GENERIC-FUNCTION MY-OBJECT-IS-IMPOSSIBLE-TO-GET> does not
	 have a method with qualifiers NIL specializers
	 ((EQL 3735928559) #<BUILT-IN-CLASS T>)

  USER(43): (find-method #'my-object-is-impossible-to-get nil
			 `((eql +magic-number+) ,(find-class 't)))
  Error: The generic function
	 #<STANDARD-GENERIC-FUNCTION MY-OBJECT-IS-IMPOSSIBLE-TO-GET> does not
	 have a method with qualifiers NIL specializers
	 ((EQL +MAGIC-NUMBER+) #<BUILT-IN-CLASS T>)

I must be overlooking something obvious. This shouldn't be that difficult,
but I've been slaving over the HyperSpec and DejaNews for hours now and I
can't find a single example of FIND-METHOD or REMOVE-METHOD on
EQL-specialized methods.

There was a thread in c.l.l during 3/99 started by Marco about "collecting
EQL-specialized methods" and he mentioned calling REMOVE-METHOD on
EQL-specialized methods. I'd love to see the syntax for doing this.

Christopher

From: Christopher R. Barry
Subject: Update: Allegro CL bug. (was Re: How do I get an EQL-specialized method's object?)
Date: 
Message-ID: <87oge1tpab.fsf@2xtreme.net>
······@2xtreme.net (Christopher R. Barry) writes:

[...]

> Now with an EQL-specializer:
> 
>   USER(38): (defconstant +magic-number+ #xDEADBEEF)
>   +MAGIC-NUMBER+
> 
>   USER(39): (defmethod my-object-is-impossible-to-get ((n (eql +magic-number+))
> 						       some-object)
> 	      'blah)
>   #<STANDARD-METHOD MY-OBJECT-IS-IMPOSSIBLE-TO-GET ((EQL 3735928559) T)>
> 
> And two slightly different attempts at getting the object:
> 
>   USER(41): (find-method #'my-object-is-impossible-to-get nil
> 			 `((eql ,+magic-number+) ,(find-class 't)))
>   Error: The generic function
> 	 #<STANDARD-GENERIC-FUNCTION MY-OBJECT-IS-IMPOSSIBLE-TO-GET> does not
> 	 have a method with qualifiers NIL specializers
> 	 ((EQL 3735928559) #<BUILT-IN-CLASS T>)

[...]

Before sending this post I didn't try this with any other Lisp. This
works with every other Lisp I've tried it on. [The Lisp in the above
example is Allegro CL 5.0.1 Trial Edition on Linux/x86.]

I guess I'll make a bug report. That was a good waste of the better
part of my day....

[The lesson to be learned here is to always try things out that
_should_ work on another Lisp.]

Christopher
From: Duane Rettig
Subject: Re: Update: Allegro CL bug. (was Re: How do I get an EQL-specialized method's object?)
Date: 
Message-ID: <4puyg35kq.fsf@beta.franz.com>
······@2xtreme.net (Christopher R. Barry) writes:

> [...]
> 
> Before sending this post I didn't try this with any other Lisp. This
> works with every other Lisp I've tried it on. [The Lisp in the above
> example is Allegro CL 5.0.1 Trial Edition on Linux/x86.]
> 
> I guess I'll make a bug report. That was a good waste of the better
> part of my day....
> 
> [The lesson to be learned here is to always try things out that
> _should_ work on another Lisp.]

It's unfortunate that you feel you wasted time on this, but I believe
that you drew the wrong conclusion about the lesson learned.

I won't claim that the other implementations are wrong, because
accepting `(eql ,x) as an actual specializer metaobject is not
well specified in the ANSI spec.  However, I would also make a
strong guess that each of those implementations do not implement
intern-eql-specializer (AMOP, p 206), so whether or not you send
a bug report to each depends on whether they are supporting the MOP.

For the sake of portability, you could define a trivial version
that would work for those implementations that don't have one:

#-(or allegro ???)
(defun intern-eql-specializer (object)
  `(eql ,object))

I do have a problem reconciling the AMOP specification with this
definition, which is returning a cons and calling it an eql
specializer metaobject.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Christopher R. Barry
Subject: Not an Allegro CL bug (was Re: Update: Allegro CL bug. (was Re: How do I get an EQL-specialized method's object?))
Date: 
Message-ID: <87bta0ts5l.fsf_-_@2xtreme.net>
······@2xtreme.net (Christopher R. Barry) writes:

> [The lesson to be learned here is to always try things out that
> _should_ work on another Lisp.]

The _real_ lesson to be learned here is that Lisps which correctly
implement standard extensions (like the MOP) to core ANSI CL
functionality (like CLOS), may have to incompatibly change the way you
accomplished a particular thing with an ANSI CL that doesn't implement
that extension.

FWIW, passing an EQL-specializer's _object_ instead of its name (as
you must do with Allegro CL or a Lisp that implements
INTERN-EQL-SPECIALIZER from the MOP) is more elegant and consistent
since you pass the object instead of name for every other parameter.

Christopher
From: Pekka P. Pirinen
Subject: Re: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <ixbta0u998.fsf@gaspode.cam.harlequin.co.uk>
······@2xtreme.net (Christopher R. Barry) writes:
>   USER(41): (find-method #'my-object-is-impossible-to-get nil
> 			 `((eql ,+magic-number+) ,(find-class 't)))
>   Error: The generic function
> 	 #<STANDARD-GENERIC-FUNCTION MY-OBJECT-IS-IMPOSSIBLE-TO-GET> does not
> 	 have a method with qualifiers NIL specializers
> 	 ((EQL 3735928559) #<BUILT-IN-CLASS T>)

Your Lisp implementation is broken: that's supposed to work (and it
does in LispWorks).  It might be interesting to try that with a
+MAGIC-NUMBER+ that is a fixnum.  Inspecting the method object might
reveal some hack to get around this, but probably not.  If you really
need to do this from a program, you need to add some protocol of your
own.  There's a MOP function called GENERIC-FUNCTION-METHODS that
might help (if your Lisp has it).
-- 
Pekka P. Pirinen
Adaptive Memory Management Group, Harlequin Limited
If you don't succeed at first, try again. Then quit. No use of being a
damn fool about it.  - W. C. Fields
From: Pekka P. Pirinen
Subject: Re: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <ix9054u1ct.fsf@gaspode.cam.harlequin.co.uk>
·····@harlequin.co.uk (Pekka P. Pirinen) writes:
> [FIND-METHOD didn't work on EQL specializers] If you really
> need to do this from a program, you need to add some protocol of your
> own.  There's a MOP function called GENERIC-FUNCTION-METHODS that [...]

No sooner had I sent this, than I realized that the simplest
workaround is probably COMPUTE-APPLICABLE-METHODS.
-- 
Pekka P. Pirinen
Adaptive Memory Management Group, Harlequin Limited
Speak in haste, repent at leasure.
From: Duane Rettig
Subject: Re: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <4r9iw36ks.fsf@beta.franz.com>
······@2xtreme.net (Christopher R. Barry) writes:

> This is driving me insane. If I have a method that has an (EQL <object>)
> specializer, how do I call FIND-METHOD on it? Example:
> 
  ...
> 
> Now with an EQL-specializer:
> 
>   USER(38): (defconstant +magic-number+ #xDEADBEEF)
>   +MAGIC-NUMBER+
> 
>   USER(39): (defmethod my-object-is-impossible-to-get ((n (eql +magic-number+))
> 						       some-object)
> 	      'blah)
>   #<STANDARD-METHOD MY-OBJECT-IS-IMPOSSIBLE-TO-GET ((EQL 3735928559) T)>

Find-method needs a list of specializers, not names or specs for
specializers.  The way to create an eql specializer is not given in
the ANSI spec, but instead in AMOP, p 206, via intern-eql-specializer:

USER(3): (find-method #'my-object-is-impossible-to-get nil
			 `(,(clos:intern-eql-specializer +magic-number+) ,(find-class 't)))
#<STANDARD-METHOD MY-OBJECT-IS-IMPOSSIBLE-TO-GET ((EQL 3735928559) T)>
USER(4): 


> I must be overlooking something obvious. This shouldn't be that difficult,
> but I've been slaving over the HyperSpec and DejaNews for hours now and I
> can't find a single example of FIND-METHOD or REMOVE-METHOD on
> EQL-specialized methods.

It is not at all obvious.  And, in truth, it may be that other
implementations consider that `(eql ,+magic-number+) is by definition
a specializer, but if so, the fact that the specializer is in fact a
cons makes it harder to discriminate.  In Allegro CL, 
intern-eql-specializer returns a discriminable clos object distinct
from a cons whose car happens to be 'eql.

> There was a thread in c.l.l during 3/99 started by Marco about "collecting
> EQL-specialized methods" and he mentioned calling REMOVE-METHOD on
> EQL-specialized methods. I'd love to see the syntax for doing this.

The above discussion should give you fodder for this.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Bruno Haible
Subject: Re: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <7u7pn2$i49$1@news.u-bordeaux.fr>
Duane Rettig <·····@franz.com> wrote:
>
>> I must be overlooking something obvious. This shouldn't be that difficult,
>> but I've been slaving over the HyperSpec and DejaNews for hours now and I
>> can't find a single example of FIND-METHOD or REMOVE-METHOD on
>> EQL-specialized methods.
>
> It is not at all obvious.  And, in truth, it may be that other
> implementations consider that `(eql ,+magic-number+) is by definition
> a specializer

Right. The wording in ANSI CL (sec_7-6-2.html) is clear:

   Because every valid parameter specializer is also a valid type
   specifier, the function `typep' can be used during method selection
   to determine whether an argument satisfies a parameter specializer. 

Which means that the implementation might choose a non-evident representation
for the parameter specializer, e.g.  `(SYSTEM:%EQL ,+magic-number+).

> In Allegro CL, intern-eql-specializer returns a discriminable clos object

But this discriminable clos object is acceptable as second argument to
`typep', right?

                               Bruno                     http://clisp.cons.org/
From: Duane Rettig
Subject: Re: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <4oge02zdu.fsf@beta.franz.com>
······@clisp.cons.org (Bruno Haible) writes:

> Duane Rettig <·····@franz.com> wrote:
> > It is not at all obvious.  And, in truth, it may be that other
> > implementations consider that `(eql ,+magic-number+) is by definition
> > a specializer
> 
> Right. The wording in ANSI CL (sec_7-6-2.html) is clear:
> 
>    Because every valid parameter specializer is also a valid type
>    specifier, the function `typep' can be used during method selection
>    to determine whether an argument satisfies a parameter specializer. 
> 
> Which means that the implementation might choose a non-evident representation
> for the parameter specializer, e.g.  `(SYSTEM:%EQL ,+magic-number+).

Correct.  Unfortunately for implementations that choose this, it
overloads CONSP to check the car of the cons for the special indicator,
before it is able to return true.

> > In Allegro CL, intern-eql-specializer returns a discriminable clos object
> 
> But this discriminable clos object is acceptable as second argument to
> `typep', right?

Well, technically, yes, but you've brought out a bug, because it
doesn't give the right answer :-(

USER(47): (setq x (clos:intern-eql-specializer 1))
#<CLOS:EQL-SPECIALIZER 1 @ #x204f94b2>
USER(48): (typep x 'clos:eql-specializer)
T
USER(49): (typep 1 '(eql 1))
T
USER(50): (typep 1 x)
NIL                       <-- oops!
USER(51): 

I'll be filing a bug report internally.  Meanwhile, those who want to
use typep can work around the problem by using the "parameter
specializer name" (e.g. '(eql 1) as defined in sec 7.6.2) rather than
the actual "parameter specializer" (the interned specializer object)
when calling typep.

We probably haven't seen this bug before because most people who deal
with eql-specilizers use the name anyway.  In fact, it is the reason for
this thread, though it is clear that find-method wants specializers,
and not their names.

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Pekka P. Pirinen
Subject: Re: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <ixiu4422gl.fsf@gaspode.cam.harlequin.co.uk>
Duane Rettig <·····@franz.com> writes:
> USER(47): (setq x (clos:intern-eql-specializer 1))
> #<CLOS:EQL-SPECIALIZER 1 @ #x204f94b2>
> USER(50): (typep 1 x)
> NIL                       <-- oops!
> 
> I'll be filing a bug report internally.  Meanwhile, those who want to
> use typep can work around the problem by using the "parameter
> specializer name" (e.g. '(eql 1) as defined in sec 7.6.2) rather than
> the actual "parameter specializer" (the interned specializer object)
> when calling typep.

(EQL 1) does work with TYPEP, but not because it's the "parameter
specializer name"; That contains a form (e.g., +MAGIC-NUMBER+) that
must be evaluated to get the object to use in (TYPEP x '(EQL
<object>)).  It's only when you have a self-evaluating form, like 1,
that the two are the same.  I'm sure you knew that, except on Fridays.

Such EQL-SPECIALIZER objects can speed up dispatch, although it seems
to me this could be hidden from a non-MOP user.  Reading the spec, I
can see that 7.6.2 leaves the door open for this by saying "(EQL form)
denotes a parameter specializer which _satisfies_ the type specifier
(EQL object)" (my emphasis), whereas all the other clauses on
parameter specializer names just say: "denotes a specializer which
_is_", but it just sounds like an editing problem to me.  The glossary
definition of "parameter specializer" clearly states "a class, or a
list (EQL object)".
-- 
Pekka P. Pirinen
Adaptive Memory Management Group, Harlequin Limited
A feature is a bug with seniority.  - David Aldred <david_aldred.demon.co.uk>
From: Christopher R. Barry
Subject: Re: How do I get an EQL-specialized method's object?
Date: 
Message-ID: <87zoxks856.fsf@2xtreme.net>
······@clisp.cons.org (Bruno Haible) writes:

> Duane Rettig <·····@franz.com> wrote:
> >
> >> I must be overlooking something obvious. This shouldn't be that difficult,
> >> but I've been slaving over the HyperSpec and DejaNews for hours now and I
> >> can't find a single example of FIND-METHOD or REMOVE-METHOD on
> >> EQL-specialized methods.
> >
> > It is not at all obvious.  And, in truth, it may be that other
> > implementations consider that `(eql ,+magic-number+) is by definition
> > a specializer
> 
> Right. The wording in ANSI CL (sec_7-6-2.html) is clear:
> 
>    Because every valid parameter specializer is also a valid type
>    specifier, the function `typep' can be used during method selection
>    to determine whether an argument satisfies a parameter specializer. 
> 
> Which means that the implementation might choose a non-evident representation
> for the parameter specializer, e.g.  `(SYSTEM:%EQL ,+magic-number+).
> 
> > In Allegro CL, intern-eql-specializer returns a discriminable clos object
> 
> But this discriminable clos object is acceptable as second argument to
> `typep', right?

  USER(10): (typep (clos:intern-eql-specializer +magic-number+)
		   'clos:eql-specializer)
  T

Christopher