From: basman
Subject: accessing method objects of a generic function
Date: 
Message-ID: <1130609984.648273.64510@o13g2000cwo.googlegroups.com>
Suppose I have a generic function object foo.  Now I want access to the
list of method objects of foo, and information about those methods,
such as their type signatures and documentation strings.  Is there a
way to do this?
- Bhaskara

From: Bill Atkins
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <1130610380.758853.151070@z14g2000cwz.googlegroups.com>
CL-USER> (defgeneric foo (x)
	   (:documentation "generic foo"))
#<STANDARD-GENERIC-FUNCTION FOO (0)>

CL-USER> (defmethod foo ((x integer))
	   "Foo this integer"
	   (+ x 4))
#<STANDARD-METHOD FOO (INTEGER) {A014FC1}>

CL-USER> (defmethod foo ((x string))
	   "Foo this string"
	   (concatenate 'string x "foo"))
#<STANDARD-METHOD FOO (STRING) {91235E1}>

CL-USER> (describe #'foo)
#<STANDARD-GENERIC-FUNCTION FOO (2)> is a generic function.
Its documentation is: generic foo
Its lambda-list is:
  (X)
Its method-combination is:
  #<SB-PCL::STANDARD-METHOD-COMBINATION STANDARD NIL {501AC49}>
Its methods are:
  (FOO (STRING))
    Method documentation: Foo this string
  (FOO (INTEGER))
    Method documentation: Foo this integer
; No value
CL-USER>
From: Pascal Costanza
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <3shtocFo9uijU1@individual.net>
basman wrote:
> Suppose I have a generic function object foo.  Now I want access to the
> list of method objects of foo, and information about those methods,
> such as their type signatures and documentation strings.  Is there a
> way to do this?

Bill Atkins has described how to get a description of such information 
that is mostly useful at development time.

If you want to access such information programmatically, this is covered 
by the introspective functions of the CLOS Metaobject Protocol (MOP).

More specifically, generic-function-methods returns a list of the 
methods associated with a generic function, and method-qualifiers, 
method-lambda-list, method-specializers and method-function return the 
components of a method definition.

See http://www.lisp.org/mop/index.html for a specification of the CLOS 
MOP. Check with the documentation of your preferred Common Lisp 
implementation to what extent the CLOS MOP is supported or not. (The 
CLOS MOP is not required by ANSI Common Lisp, so CL implementations may 
choose not to support it.)


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: basman
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <1130612272.644537.84780@g43g2000cwa.googlegroups.com>
Hmm, so I tried describe as per Bill's suggestion.  However, in my
implementation (Allegro) it doesn't print out the doc strings of the
methods.  Also, I would like the piece of software I'm writing to run
on all ANSI-compliant Lisps... is there no universally supported way to
access the methods of a generic function?  I guess I could always write
special-case code for each of the commonly used Lisp implementations...


Pascal Costanza wrote:
> basman wrote:
> > Suppose I have a generic function object foo.  Now I want access to the
> > list of method objects of foo, and information about those methods,
> > such as their type signatures and documentation strings.  Is there a
> > way to do this?
>
> Bill Atkins has described how to get a description of such information
> that is mostly useful at development time.
>
> If you want to access such information programmatically, this is covered
> by the introspective functions of the CLOS Metaobject Protocol (MOP).
>
> More specifically, generic-function-methods returns a list of the
> methods associated with a generic function, and method-qualifiers,
> method-lambda-list, method-specializers and method-function return the
> components of a method definition.
>
> See http://www.lisp.org/mop/index.html for a specification of the CLOS
> MOP. Check with the documentation of your preferred Common Lisp
> implementation to what extent the CLOS MOP is supported or not. (The
> CLOS MOP is not required by ANSI Common Lisp, so CL implementations may
> choose not to support it.)
>
>
> Pascal
>
> --
> My website: http://p-cos.net
> Closer to MOP & ContextL:
> http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <3si0dnFo84v0U1@individual.net>
basman wrote:
> Hmm, so I tried describe as per Bill's suggestion.  However, in my
> implementation (Allegro) it doesn't print out the doc strings of the
> methods.  Also, I would like the piece of software I'm writing to run
> on all ANSI-compliant Lisps... is there no universally supported way to
> access the methods of a generic function?  I guess I could always write
> special-case code for each of the commonly used Lisp implementations...

If you want to stick to ANSI CL, there are some possible workarounds:

- defmethod returns the method object for the method it creates. You 
could write your own defmethod* macro that expands into a form which 
calls defmethod and stores that method somewhere. (Not particularly nice 
because then the defmethod is not a top-level form anymore which has a 
few disadvantages.)

- If you only want to get the documentation, you can call the function 
documentation on such objects - it is a function defined in ANSI CL, and 
explicitly specified to work on method objects.

However, I wouldn't worry too much about possible incompatibilities when 
using the introspective features of the CLOS MOP. The number of CL 
implementations that support the CLOS MOP is relatively large and covers 
the most important ones. There are some incompatibilities in the 
different MOPs, but the introspective features are overall very well 
supported without any real issues. (The intercessive features - where 
you can change the semantics of CLOS - are more problematic in this regard.)

Allegro has good support for the CLOS MOP, and it provides the MOP 
documentation as part of its overall set of documentation.

If you want to worry less about possible incompatibilities, here is a 
shameless plug: check out http://common-lisp.net/project/closer/ that 
contains the Closer to MOP library that irons out some of the 
incompatibilities across several CL implementations, and provides a 
single package that you can use in all of the supported implementations.

However, let me stress again: The introspective functions do not really 
need such a compatibility layer. The chances that you paint yourself 
into a corner are pretty low here.


Cheers,
Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: basman
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <1130616458.210404.305040@g44g2000cwa.googlegroups.com>
OK, I'll look into the introspective MOP functions, and go with that if
it seems well supported across Lisps.
Thanks,
Bhaskara
From: Peter Seibel
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <m2r7a42idr.fsf@gigamonkeys.com>
Pascal Costanza <··@p-cos.net> writes:

> If you want to stick to ANSI CL, there are some possible workarounds:
>
> - defmethod returns the method object for the method it creates. You
>   could write your own defmethod* macro that expands into a form which
>   calls defmethod and stores that method somewhere. (Not particularly
>   nice because then the defmethod is not a top-level form anymore
>   which has a few disadvantages.)

Is there some reason you Can't fix that with appropriate use of
EVAL-WHEN in the expansion of DEFMETHOD*?

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Pascal Costanza
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <3si96kFojp8nU1@individual.net>
Peter Seibel wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
>>If you want to stick to ANSI CL, there are some possible workarounds:
>>
>>- defmethod returns the method object for the method it creates. You
>>  could write your own defmethod* macro that expands into a form which
>>  calls defmethod and stores that method somewhere. (Not particularly
>>  nice because then the defmethod is not a top-level form anymore
>>  which has a few disadvantages.)
> 
> Is there some reason you Can't fix that with appropriate use of
> EVAL-WHEN in the expansion of DEFMETHOD*?

OK, your idea is to say something like this, right?

(defmacro defmethod* (...)
   `(eval-when (:compile-toplevel ...)
      (let ((m (defmethod ...)))
        ...)))

This will indeed create the method at compile time. But will this also 
produce the compile-time effects that a defmethod has when it is in a 
top-level position itself? I don't think so.

I am referring to the following statement in the HyperSpec: "An 
implementation may choose to store information about the generic 
function for the purposes of compile-time error-checking (such as 
checking the number of arguments on calls, or noting that a definition 
for the function name has been seen)." I think this also includes 
performing certain compile-time optimizations that a CL compiler can 
only perform when it knows at compile-time that a generic function will 
exist.

But I have to admit that I am not 100% sure about this...


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Peter Seibel
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <m2mzks2csk.fsf@gigamonkeys.com>
Pascal Costanza <··@p-cos.net> writes:

> Peter Seibel wrote:
>> Pascal Costanza <··@p-cos.net> writes:
>> 
>>>If you want to stick to ANSI CL, there are some possible workarounds:
>>>
>>>- defmethod returns the method object for the method it creates. You
>>>  could write your own defmethod* macro that expands into a form which
>>>  calls defmethod and stores that method somewhere. (Not particularly
>>>  nice because then the defmethod is not a top-level form anymore
>>>  which has a few disadvantages.)
>> Is there some reason you Can't fix that with appropriate use of
>> EVAL-WHEN in the expansion of DEFMETHOD*?
>
> OK, your idea is to say something like this, right?
>
> (defmacro defmethod* (...)
>    `(eval-when (:compile-toplevel ...)
>       (let ((m (defmethod ...)))
>         ...)))

Ah, I missed the point that you need to capture the value returned by
DEFMETHOD. Duh. Yeah, I can't think of any way to both capture the
return value and have DEFMETHOD processed as a top-level
form. Interesting.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Steven M. Haflich
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <J4Caf.9464$7h7.4320@newssvr21.news.prodigy.com>
Peter Seibel wrote:
> 
> Ah, I missed the point that you need to capture the value returned by
> DEFMETHOD. Duh. Yeah, I can't think of any way to both capture the
> return value and have DEFMETHOD processed as a top-level
> form. Interesting.

First of all, I think the defmethod* approach is the wrong approach,
since the MOP provides a way to do this introspection directly, as
has been pointed out by other posters.

But if one were to use the defmethod* approach, why are you so
concerned with maintaining top-level-ness of the defmethod form?
Unlike some other defining forms, defmethod has _no_ special
semantics at top level.  (Unless I'm forgetting something, or
misremembering the negation of that something.)

It may be that you want to preserve the additional compiler
services in some particular implementation, such as interface to
the development environments editor. This is obviously not
portable, but the effects can usually be attained by macroexpansion
into implementation-dependent eval-when compile forms.  It would be
nice if some of these top-level defining-form extensions were
portable between different implementations, but they ain't.
From: Pascal Costanza
Subject: Re: accessing method objects of a generic function
Date: 
Message-ID: <3t0it7Fq917hU1@individual.net>
Steven M. Haflich wrote:

> But if one were to use the defmethod* approach, why are you so
> concerned with maintaining top-level-ness of the defmethod form?
> Unlike some other defining forms, defmethod has _no_ special
> semantics at top level.  (Unless I'm forgetting something, or
> misremembering the negation of that something.)

In many implementations, a top-level defmethod form makes the compiler 
note that the corresponding generic function will be available and, for 
example, lets it check correct number of arguments when the function is 
called, without the need to "announce" the generic function with a 
defgeneric form.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/