From: Thomas A. Russ on
peder(a)news.klingenberg.no (Peder O. Klingenberg) writes:

> You could always do it by hand:
>
> (defun fsolve (solver &key ...)
> (if (member (type-of solver)
> '(multi-dimensional-root-solver-f
> multi-dimensional-root-solver-fdf))
> (fsolve-1 solver absolute-error max-iteration print-steps)
> (error 'type-error ...))))

Or even simpler:

(defun fsolve (solver &key ...)
(etypecase solver
((multi-dimensional-root-solver-f
multi-dimensional-root-solver-fdf)
(fsolve-1 solver ...))))

--
Thomas A. Russ, USC/Information Sciences Institute
From: Peder O. Klingenberg on
tar(a)sevak.isi.edu (Thomas A. Russ) writes:

> Or even simpler:
>
> (defun fsolve (solver &key ...)
> (etypecase solver
> ((multi-dimensional-root-solver-f
> multi-dimensional-root-solver-fdf)
> (fsolve-1 solver ...))))

Etypecase was actually the first thing that crossed my mind, but I
checked the hyperspec, and each clause has the form (type form*) - only
a single type is allowed. Which led me to abandon that approach.

Thinking about it some more, I guess you could use the type specifier
(or multi-dimensional-root-solver-f multi-dimensional-root-solver-fdf)
and use something very similar to your example, but I don't think
skipping the 'or is allowed.

....Peder...
--
I wish a new life awaited _me_ in some off-world colony.

From: Tim Bradshaw on
On 2010-06-16 20:32:36 +0100, Peder O. Klingenberg said:

> Etypecase was actually the first thing that crossed my mind, but I
> checked the hyperspec, and each clause has the form (type form*) - only
> a single type is allowed. Which led me to abandon that approach.

If t1 and t2 are types then (OR t1 t2) is a type which is either t1 or t2.

From: Thomas A. Russ on
Leo <sdl.web(a)gmail.com> writes:

> On 2010-06-16 05:40 +0100, Barry Margolin wrote:
> > Define a class fsolve-1-er, and make this a superclass of both
> > multi-dimensional-root-solver-f and multi-dimensional-root-solver-fdf.
> > Then define the method:
> >
> > (defmethod fsolve ((solver fsolve-1-er)
> > &key ...)
> > (fsolve-1 solver absolute-error max-iteration print-steps))
>
> The two classes are from a common lisp package named GSLL. I am trying
> to do things in my own package instead of modifying GSLL. Is that
> possible? Thanks.

Well, Barry's suggestion would be the best case, but it won't help you
if you are using a library which already defines these classes. You
wouldn't be able to add a superclass without redefining the classes.

So you are then left with other potential solutions:

(1) Do your own type dispatch using TYPECASE (see a different answer)
(2) Create your own "shadow" type hierarchy by defining
(defclass my-solver () ())
(defclass my-root-solver-f (my-solver
(multi-dimensional-root-solver-f))
())
(defclass my-root-solver-fdf (my-solver
(multi-dimensional-root-solver-fdf))
())

and then only use your own solver classes instead of the supplied
ones for all of your work.
(3) Create a delegated class structure where you have your own holder
class. This is a bit more work than (2) because you have to
arrange to pass all the methods through to the delegate.

(defclass my-solver-proxy ()
((root-solver :init-arg :root-solver)))

Unfortunately, I don't know of any way to automatically forward
generic function calls where there is no method defined for
MY-SOLVER on to (root-solver my-solver-instance). I didn't see
anything that looked like a solution in the MOP either.

Is there a MOP-based solution?
I think the problem is that there can't be any method that involves
the types of the arguments because you wouldn't have a fixed set of
dispatch arguments for ALL generic functions.

This is a hack with defining and :AROUND method on
NO-APPLICABLE-METHOD, but that wouldn't work more than once and
would be frowned upon:

(defmethod no-applicable-method :around
(generic-function &rest arguments)
(if (and arguments
(typep (first arguments) 'my-solver-proxy))
(apply generic-function
(root-solver (first arguments))
(rest arguments))
(call-next-method)))



--
Thomas A. Russ, USC/Information Sciences Institute
From: Thomas A. Russ on
Tim Bradshaw <tfb(a)tfeb.org> writes:

> On 2010-06-16 20:32:36 +0100, Peder O. Klingenberg said:
>
> > Etypecase was actually the first thing that crossed my mind, but I
> > checked the hyperspec, and each clause has the form (type form*) - only
> > a single type is allowed. Which led me to abandon that approach.
>
> If t1 and t2 are types then (OR t1 t2) is a type which is either t1 or t2.

Thanks Tim and Peder. I had forgotten that difference between typecase and case.

--
Thomas A. Russ, USC/Information Sciences Institute