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
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)