From: Conrad Barski
Subject: UNDEFMETHOD
Date: 
Message-ID: <a4af10cf.0310180714.3b5060e9@posting.google.com>
Once one has DEFMETHODed a function, but needs to change its
parameters into something non-congruent, CL will raise an exception,
unless you reboot the environment.

If one is still in the design stage and is still working out the exact
parameters, this can become pretty annoying. Is there any trick in CL
for UNDEFMETHODing something, so that you can continue working after
this happens?

From: Howard Ding <······@hading.dnsalias.com>
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <m38yni606q.fsf@frisell.localdomain>
·····················@yahoo.com (Conrad Barski) writes:

> Once one has DEFMETHODed a function, but needs to change its
> parameters into something non-congruent, CL will raise an exception,
> unless you reboot the environment.
>
> If one is still in the design stage and is still working out the exact
> parameters, this can become pretty annoying. Is there any trick in CL
> for UNDEFMETHODing something, so that you can continue working after
> this happens?

Doesn't fmakunbound do it?

-- 
Howard Ding
<······@hading.dnsalias.com>
From: Kent M Pitman
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <wkad7b8dwf.fsf@nospam.nhplace.com>
······@hading.dnsalias.com (Howard Ding <······@hading.dnsalias.com>) writes:

> ·····················@yahoo.com (Conrad Barski) writes:
> 
> > Once one has DEFMETHODed a function, but needs to change its
> > parameters into something non-congruent, CL will raise an exception,
> > unless you reboot the environment.

In some environments, this exception will offer you a restart that will
discard old methods and change the method signature.  It's a clumsy 
interface, but works...

> > If one is still in the design stage and is still working out the exact
> > parameters, this can become pretty annoying. Is there any trick in CL
> > for UNDEFMETHODing something, so that you can continue working after
> > this happens?
> 
> Doesn't fmakunbound do it?

Yes, and if it doesn't work, UNINTERN often helps.

Some development environments also offer a m-x undefine or m-x undefun
kind of facility.

- - - - - 

Incidentally, in the case of arglist-compatible redefinition, if you
don't have an undefine feature, I sometimes write:

 (defmethod foo ((x fixnum) (y symbol)) (call-next-method))

as a substitute for an undefinition of a method on foo for fixnum x
symbol [just as an example].  This comes up in macro writing once in
a while, if you have a conditionally-generated method and you want the
change of an option to undo a possible prior generation of a method;
consider:

 (defmacro define-something (name &key ... (record-access t) ...)
   `(progn
       ...
       ,(if record-access
          `(defmethod access-foo :after ((x frob)) 
             (push `(accessed ,x ,(get-universal-time)) *accesses*))
          `(defmethod access-foo :after ((x frob))
             (call-next-method)))
       ...))

if you leave that arm of the method blank, you'll end up sometimes with
stale methods from a prior definition.
From: Dan Corkill
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <3F915DA9.2040906@comcast.net>
Conrad Barski wrote:
> Once one has DEFMETHODed a function, but needs to change its
> parameters into something non-congruent, CL will raise an exception,
> unless you reboot the environment.
> 
> If one is still in the design stage and is still working out the exact
> parameters, this can become pretty annoying. Is there any trick in CL
> for UNDEFMETHODing something, so that you can continue working after
> this happens?

Here's what I use regularly...  easy to add "un" to a defmethod form
and back it out of the environment:

;;; ===========================================================================
;;;  Method Removal (based on Zack Rubinstein's original concept)
;;;
;;;  Note: this does not work well with some eql specializers

(defun find-and-remove-method (generic-function method-qualifiers
                                specialized-lambda-list)
   (flet ((make-qualifier (name)
            (if (and (consp name)
                     (eq (first name) 'eql))
                (intern-eql-specializer (eval (second name)))
                (find-class name))))
     (declare (dynamic-extent #'make-qualifier))
     (let* ((specializer-names
             (extract-specializer-names specialized-lambda-list))
            (method-object
             (find-method generic-function
                          (assure-list method-qualifiers)
                          (mapcar #'make-qualifier specializer-names)
                          ;; don't signal errors
                          nil)))
       (if method-object
           (remove-method generic-function method-object)
           (warn "Unable to locate method ~s ~s ~s"
                 generic-function
                 method-qualifiers
                 specializer-names)))))

;;; ---------------------------------------------------------------------------

(flet ((method-qualifiers-p (spec)
          (or (null spec)
              (keywordp spec)
              (and (consp spec)
                   (every #'keywordp spec)))))
   (defmacro undefmethod (method-name maybe-qualifiers &rest args)
     (if (method-qualifiers-p maybe-qualifiers)
         `(find-and-remove-method
           #',method-name ',maybe-qualifiers ',(first args))
         `(find-and-remove-method
           #',method-name nil ',maybe-qualifiers))))

;;; ===========================================================================
From: Frode Vatvedt Fjeld
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <2h7k32pnij.fsf@vserver.cs.uit.no>
·····················@yahoo.com (Conrad Barski) writes:

> Once one has DEFMETHODed a function, but needs to change its
> parameters into something non-congruent, CL will raise an exception,
> unless you reboot the environment.

I think any reasonable development environment will offer a restart
that continues by redefining the generic function.

Otherwise, you can always manually fmakunbound the generic function's
name.

> If one is still in the design stage and is still working out the
> exact parameters, this can become pretty annoying. Is there any
> trick in CL for UNDEFMETHODing something, so that you can continue
> working after this happens?

When you grow more confident in Common Lisp, you will have learned to
ask "how", not "if" about basic things such as these :)

-- 
Frode Vatvedt Fjeld
From: Conrad Barski
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <a4af10cf.0310181457.16ad067b@posting.google.com>
> When you grow more confident in Common Lisp, you will have learned to
> ask "how", not "if" about basic things such as these :)

Ah yes, but is it not true that in FP you express not "how" but "what"?

Hmmm?

How do you explain that, Mr. Frode Vatvedt Fjeld, if that really is your name?

:)
From: Frode Vatvedt Fjeld
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <2hbrseno2u.fsf@vserver.cs.uit.no>
·····················@yahoo.com (Conrad Barski) writes:

> Ah yes, but is it not true that in FP you express not "how" but
> "what"?

You make take this as conclusive evidence that CL is not FP..

-- 
Frode Vatvedt Fjeld
From: james anderson
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <3F91657F.88B8A717@setf.de>
Conrad Barski wrote:
> 
> Once one has DEFMETHODed a function, but needs to change its
> parameters into something non-congruent, CL will raise an exception,
> unless you reboot the environment.
> 
> If one is still in the design stage and is still working out the exact
> parameters, this can become pretty annoying. Is there any trick in CL
> for UNDEFMETHODing something, so that you can continue working after
> this happens?

if all of the methods were defined as clauses of a defgeneric form, (ie not
literally with defmethod), defgeneric should be able to change the function's
signature, as it should remove all of those functions as a first stage in the redefinition.

if additional methods were defined with defmethod, one can always remove them
by a combination of the functions generic-function-methods and remove-method. 

an undefmethod macro does make this easier, and can be readily defined using
find-method and the other two functions noted above. one may, however, be able
to avail onself of tools in ones development environment. i'm not sure where
to find my implementation of undefmethod any more, as, in the case of mcl, a
"remove method" option as been present in the inspector for several years.

...
From: Nils Goesche
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <877k31kggz.fsf@darkstar.cartan>
james anderson <··············@setf.de> writes:

> Conrad Barski wrote:
> > 
> > Once one has DEFMETHODed a function, but needs to change its
> > parameters into something non-congruent, CL will raise an
> > exception, unless you reboot the environment.

The Gray Eminence just told me that the right way to do this is
to simply use DEFGENERIC.

> > If one is still in the design stage and is still working out
> > the exact parameters, this can become pretty annoying. Is
> > there any trick in CL for UNDEFMETHODing something, so that
> > you can continue working after this happens?
> 
> if all of the methods were defined as clauses of a defgeneric
> form, (ie not literally with defmethod), defgeneric should be
> able to change the function's signature, as it should remove
> all of those functions as a first stage in the redefinition.

Just use DEFGENERIC in any case.  You might get an error, but it
will probably be continuable, like

CL-USER 8 > (defgeneric blubb (x))
#<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>

CL-USER 9 > (defgeneric blubb (x y))

Error: Lambda list (X Y) is not congruent with the lambda list (X) of the generic function #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>.
  1 (continue) Modify the lambda list and delete existing methods of #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>.
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other options

CL-USER 10 : 1 > :c 1
#<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID #xD26EF2A0
From: james anderson
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <3F924848.7BCD59F4@setf.de>
Nils Goesche wrote:
> 
> ...
> 
> Just use DEFGENERIC in any case.  You might get an error, but it
> will probably be continuable, like
> 
> CL-USER 8 > (defgeneric blubb (x))
> #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>
> 
> CL-USER 9 > (defgeneric blubb (x y))
> 
> Error: Lambda list (X Y) is not congruent with the lambda list (X) of the generic function #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>.
>   1 (continue) Modify the lambda list and delete existing methods of #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>.
>   2 (abort) Return to level 0.
>   3 Return to top loop level 0.
> 

this is strange. if there are no methods, defgeneric should not signal an
error, but should directly change the lambda list.

...
From: Nils Goesche
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <87oewd42ag.fsf@darkstar.cartan>
james anderson <··············@setf.de> writes:

> Nils Goesche wrote:
> > 
> > ...
> > 
> > Just use DEFGENERIC in any case.  You might get an error, but it
> > will probably be continuable, like
> > 
> > CL-USER 8 > (defgeneric blubb (x))
> > #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>
> > 
> > CL-USER 9 > (defgeneric blubb (x y))
> > 
> > Error: Lambda list (X Y) is not congruent with the lambda list (X) of the generic function #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>.
> >   1 (continue) Modify the lambda list and delete existing methods of #<STANDARD-GENERIC-FUNCTION BLUBB 20671B1A>.
> >   2 (abort) Return to level 0.
> >   3 Return to top loop level 0.
> 
> this is strange. if there are no methods, defgeneric should not
> signal an error, but should directly change the lambda list.

Yes, this seems to be a bug in LispWorks.  Even if there are
existing non-congruent methods, however, I don't see any point in
signalling an error.  The wording in the HyperSpec seems to imply
that no error is signalled if the existing methods have been
defined by DEFGENERIC, in which case they are simply removed.
Why make a difference here?  Why would I change the generic
function's lambda list if I planned to keep existing methods
unchanged?  Only if I tried to recompile the DEFMETHOD form
without adjusting its lambda list, too, would it make sense to
signal an error, I think.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID #xD26EF2A0
From: Christophe Rhodes
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <sqznfxkvv4.fsf@lambda.jcn.srcf.net>
Nils Goesche <···@cartan.de> writes:

> Yes, this seems to be a bug in LispWorks.  Even if there are
> existing non-congruent methods, however, I don't see any point in
> signalling an error.  The wording in the HyperSpec seems to imply
> that no error is signalled if the existing methods have been
> defined by DEFGENERIC, in which case they are simply removed.
> Why make a difference here?  Why would I change the generic
> function's lambda list if I planned to keep existing methods
> unchanged?  Only if I tried to recompile the DEFMETHOD form
> without adjusting its lambda list, too, would it make sense to
> signal an error, I think.

Maybe you might make a mistake with your defgeneric, and you might not
welcome the instadeletion of all your state?

On the other hand, if you're going to remove methods anyway, why not
remove them before redefining the generic function?

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Nils Goesche
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <87fzhp3zxk.fsf@darkstar.cartan>
Christophe Rhodes <·····@cam.ac.uk> writes:

> Nils Goesche <···@cartan.de> writes:
> 
> > Even if there are existing non-congruent methods, however, I
> > don't see any point in signalling an error.

> Maybe you might make a mistake with your defgeneric, and you
> might not welcome the instadeletion of all your state?

Well, if I fumble around with the DEFGENERIC form and even hit
�compile� or �evaluate�, chances are I mean what I'm doing.

> On the other hand, if you're going to remove methods anyway,
> why not remove them before redefining the generic function?

Because it's inconvenient?  Now, I simply reevaluate DEFGENERIC
and invoke the �Yes, go ahead and *do it*� restart every time,
which is much faster.

Regadrs,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID #xD26EF2A0
From: james anderson
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <3F92BFE7.A4A02524@setf.de>
Nils Goesche wrote:
> 
> james anderson <··············@setf.de> writes:
> 
> ...
> > this is strange. if there are no methods, defgeneric should not
> > signal an error, but should directly change the lambda list.
> 
> Yes, this seems to be a bug in LispWorks.  Even if there are
> existing non-congruent methods, however, I don't see any point in
> signalling an error.  The wording in the HyperSpec seems to imply
> that no error is signalled if the existing methods have been
> defined by DEFGENERIC, in which case they are simply removed.

gee, i would have said "specifies" rather than "seems to imply".

> Why make a difference here?  Why would I change the generic
> function's lambda list if I planned to keep existing methods
> unchanged?

well, my rationalization was that a practical reason may be that if it throws
them away it's pretty hard for one to retrospectively determine what they were
and go find them. i note that, eg mcl keeps its source information on
deleted/incongruent independant method definitions anyway, but that was my rationalization.

there's also the awareness issue, if it simply deletes things which are not
lexically apparent, that's pretty insidious.

...
From: Nils Goesche
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <87k7714044.fsf@darkstar.cartan>
james anderson <··············@setf.de> writes:

> Nils Goesche wrote:
> > 
> > Even if there are existing non-congruent methods, however, I
> > don't see any point in signalling an error.  The wording in
> > the HyperSpec seems to imply that no error is signalled if
> > the existing methods have been defined by DEFGENERIC, in
> > which case they are simply removed.
> 
> gee, i would have said "specifies" rather than "seems to
> imply".

Sorry, I should have written �iff the existing methods...�, in
which case it is not quite as obvious :-)

> > Why make a difference here?  Why would I change the generic
> > function's lambda list if I planned to keep existing methods
> > unchanged?
> 
> well, my rationalization was that a practical reason may be
> that if it throws them away it's pretty hard for one to
> retrospectively determine what they were and go find them. i
> note that, eg mcl keeps its source information on
> deleted/incongruent independant method definitions anyway, but
> that was my rationalization.
> 
> there's also the awareness issue, if it simply deletes things
> which are not lexically apparent, that's pretty insidious.

Well, I hope it won't delete them in the source code, anyway ;-)
But if I change the lambda list in DEFGENERIC, why would I want
any of the preexisting methods remain?  /Not/ deleting them thus
making my system inconsistent would be really bad, but deleting
those methods is obviously what I want when I change the lambda
list.  I do not get furious errors whenever I change a DEFUN,
either.  Not that this is a big deal.  I'll do it anyway and
click on �yes, yes, just *do* it for chrissake!� every time...

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID #xD26EF2A0
From: james anderson
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <3F92CA66.2ECAB949@setf.de>
Nils Goesche wrote:
> 
> ...
> > there's also the awareness issue, if it simply deletes things
> > which are not lexically apparent, that's pretty insidious.
> 
> Well, I hope it won't delete them in the source code, anyway ;-)
> But if I change the lambda list in DEFGENERIC, why would I want
> any of the preexisting methods remain?  /Not/ deleting them thus
> making my system inconsistent would be really bad, but deleting
> those methods is obviously what I want when I change the lambda
> list.  I do not get furious errors whenever I change a DEFUN,
> either.  Not that this is a big deal.  I'll do it anyway and
> click on �yes, yes, just *do* it for chrissake!� every time...
> 

let us take another example. what would you suggest the development
environment do when one defines a method which could not possibly conform to
the method combination. or changes the method combination to one with which
existing definitions cannot conform.

my experience is that it is nice to be able to pop into the inspector, click
on each of the potentially offending methods and change their definition.
without regard to whether i do that before or after changing the generic
function definition.

...
From: Nils Goesche
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <87brsd3xp1.fsf@darkstar.cartan>
james anderson <··············@setf.de> writes:

> Nils Goesche wrote:
> > 
> > But if I change the lambda list in DEFGENERIC, why would I
> > want any of the preexisting methods remain?  /Not/ deleting
> > them thus making my system inconsistent would be really bad,
> > but deleting those methods is obviously what I want when I
> > change the lambda list.  I do not get furious errors whenever
> > I change a DEFUN, either.
> 
> let us take another example. what would you suggest the
> development environment do when one defines a method which
> could not possibly conform to the method combination.

Signal an error, of course, as it would if I defined a method
(with DEFMETHOD) with a non-congruent lambda list.  More
interesting is the question of what should happen if I reevaluate
DEFGENERIC giving a different method combination.  I'd probably
like old, incompatible (or possibly all) methods to be silently
purged here, too.  DEFGENERIC seems to be saying �Let's forget
about this generic function (and its methods) and start over
again�.

> or changes the method combination to one with which existing
> definitions cannot conform.

See above.

> my experience is that it is nice to be able to pop into the
> inspector, click on each of the potentially offending methods
> and change their definition.  without regard to whether i do
> that before or after changing the generic function definition.

What I do in most cases is first change the defgeneric, evaluate,
and click the error away.  Then go to the methods one by one and
change, compile and test them.  Or if there is no defgeneric,
I'll change and compile the first method, and click the restart
�Modify the lambda list and delete existing methods� and go on
from there.  The error you get in DEFMETHOD is ok, I think,
because a noncongruent lambda list there is likely to be a
mistake on the user's part.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID #xD26EF2A0
From: Conrad Barski
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <a4af10cf.0310181744.3e5aa076@posting.google.com>
Thanks everyone for your help. fmakunbound is what I was looking for-
Not obvious from the Hyperspec (but there is a mention in PG's book of
using this command exactly for this purpose.)

Dan's UNDEFMETHOD macro does not work under CMUCL, although I can see
how it could be powerful - probably because of MOP limitations.
Unfortunately, CMUCL also doesn't offer a restart option that removes
the conflicting method definition, as far as I can tell.
From: Dan Corkill
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <3F9249F6.6050600@comcast.net>
> Dan's UNDEFMETHOD macro does not work under CMUCL, although I can see
> how it could be powerful - probably because of MOP limitations.
> Unfortunately, CMUCL also doesn't offer a restart option that removes
> the conflicting method definition, as far as I can tell.

UNDEFMETHOD should work under CMUCL (it works for me with 18e) but, as in
other implementations, UNDEFMETHOD only removes a single method--not the
entire generic function.

I'm guilty of too quickly reading the original question, which
was about eliminating a GF (and ALL its methods).  UNDEFMETHOD
eliminates only a single method based on its signature. The GF and
all its other methods remain unchanged.

-- Dan

BTW, I didn't include the following items needed to make UNDEFMETHOD
work "straight out of the box:"


;;; Import MOP symbols, as needed:
(eval-when (:compile-toplevel :load-toplevel :execute)
   (import
    #+allegro
    '(aclmop::intern-eql-specializer)
    #+(or cmu sbcl)
    '(pcl::intern-eql-specializer)))

#+lispworks
(defun intern-eql-specializer (x)
   `(eql ,x))

;;; --------------------------------------------------------

(defun assure-list (x)
   (if (listp x) x (list x)))
(define-compiler-macro assure-list (x)
   (let ((xvar '#:x))
     `(let ((,xvar ,x))
        (if (listp ,xvar) ,xvar (list ,xvar)))))

;;; ---------------------------------------------------------
From: Coby Beck
Subject: Re: UNDEFMETHOD
Date: 
Message-ID: <bn0ccn$2jk9$1@otis.netspace.net.au>
"Dan Corkill" <··········@comcast.net> wrote in message
·····················@comcast.net...
>
> I'm guilty of too quickly reading the original question, which
> was about eliminating a GF (and ALL its methods).  UNDEFMETHOD
> eliminates only a single method based on its signature. The GF and
> all its other methods remain unchanged.

This is ideal when a specialized method is no longer desirable and you want
to go back to the parent's method.

Not to scorn you worthy macro, but I usually end up just quickly redefining
it to call-next-method before commenting it out or deleting it...

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")