From: Asle Olufsen
Subject: generic function redefinition
Date: 
Message-ID: <vpoff9c017.fsf@opus.nextel.no>
Someone gave me a question which was something like:

If you do (defmethod foo (x) 1) and then (defmethod foo (x y) 2) you
can get something like

> Restart actions (select using :continue):
>  0: Add method anyway and modify generic function.

How can you make lisp do the restart automatic?

Plan A:

If I had the name for the restart it could be called but I did not
find out how to get that name.  Besides this would be very
implementation dependent so I scraped this plan.  But if someone knows
how to make this plan work I would like to know.

Plan B:

Create a modify-method macro to be used instead of defmethod which
before a defmethod is eventually called checks if the argument list is
congruent and if not does a fmakunbound first.  So I did

(defmacro modify-method (name arglist &rest body)
  (let ((qualifier nil))
    (when (keywordp arglist)
      (setq qualifier (list arglist)
	    arglist (pop body)))
    `(progn (let* ((old (and (fboundp ',name)
			     (fdefinition ',name))))
	      (when (and old
			 (not (special-form-p ',name))
			 (not (macro-function ',name))
			 (or (functionp old)
			     (not (congruent-arglists-p 
				   (extract-lambda-list ,arglist) 
				   (generic-function-lambda-list old)))))
		(fmakunbound ',name)))
	    (defmethod ,name ,@qualifier ,arglist ,@body))))

But when I tried to create congruent-arglists-p I discovered that it
was a lot of tedious work and it would probably never be bug-free.  Hm
it looks like an encounter with "Greenspun's Tenth Rule of
Programming".  If someone asks me I would propose to have something
like congruent-arglists-p as part of the MOP.

Plan C:

Just do the defmethod and if an error occours, trap it and do
fmakunbound:

(defmacro modify-method (name &rest args)
  `(handler-case (defmethod ,name ,@args)
     (error (x) 
       (fmakunbound ',name)
       (defmethod ,name ,@args))))

My objection is that the case "error" is a little broad but the
standard only says "an error is signaled", so I guess that more
precision require implementation dependence.

Plan D ?


Oluf
From: Espen Vestre
Subject: Re: generic function redefinition
Date: 
Message-ID: <kwy9ed9562.fsf@merced.netfonds.no>
Asle Olufsen <ยทยทยท@opus.nextel.no> writes:

> > Restart actions (select using :continue):
> >  0: Add method anyway and modify generic function.
> 
> How can you make lisp do the restart automatic?

heh, I think I know what you need this for :-)

> Plan B:
> 
> Create a modify-method macro to be used instead of defmethod which
> before a defmethod is eventually called checks if the argument list is
> congruent and if not does a fmakunbound first. 

I don't think it's a good idea to do this with DEFMETHOD. A better idea
is to use DEFGENERIC, and then e.g. write a very simple macro MODIFY-GF
that does an FMAKUNBOUND followed by a DEFGENERIC.

-- 
  (espen)