Re: RFC: Extending method specializers



Leslie P. Polzer wrote:
Does anyone -- probably one of the "I was there" people -- know why
only specializing on EQL is allowed?

For example, it would be nice to be able to specialize on, say, a less
than relation.

Or even better, specializing on specific list elements:

(defmethod eat ((eql (car food-chain) 'SHARK)))

I wonder whether this was due to complexity or performance reasons.

Complexity, like in "yes it's possible, if you first solve the halting problem." ;)

Method dispatch can be understood as predicate dispatch, and CLOS defines two predicates for method dispatch from the start, the predicates the instance test and the eql test.

To better understand this, let's assume that you had to write methods like this:

(defmethod foo ((x (typep integer)) (y (eql 0))) ...)

The idea is that this method applies when x is of type integer and y is eql to 0. In CLOS it's actually written like this:

(defmethod foo ((x integer) (y (eql 0))) ...)

....but the semantics are the same.

What you're asking is: Why not allow other predicates there, like:

(defmethod foo ((x (primep)) (y (oddp)) (z (member 2 3 4))) ...)

....and so on.

The question is: How do we order applicable methods, when more than one method is applicable? When you have a class hierarchy, that's easy to answer - the most specific class determines the most specific method, and the most specific method is the method that is executed (first). Likewise, for eql specializers: They are defined on single objects, which are always considered more specific than the classes which they are instances of. This gives you a natural ordering.

However, what about this?

(defmethod bar ((x (primep))) ...)
(defmethod bar ((x (oddp))) ...)

If you call (bar 3), both methods match. So which one is the most specific one? It's not possible to answer this, because neither predicate specifies a subset of the other. (Not all prime numbers are odd, and not all odd numbers are prime.)

You could start by restricting the predicates to the kinds of predicates that describe strict subset relationships, and for example, reject a method on oddp when a method on primep already exists, or vice versa. But this requires you to (a) either analyze the predicate to find out what it does, or (b) restrict the predicates to a fixed set of predefined ones.

Option (a) means that you have to solve the halting problem. Assume a predicate 'forever that never returns, but just indefinitely loops. So what do you do when you define a method like this?

(defmethod baz ((x (forever))) ...)

Your predicate analyzer will fail in the general case, because of the halting problem.

Option (b) means that you select a number of predicates, and allow programmers to use them and only them. Here comes the kicker: That's what CLOS already does, the two predicates are typep and eql.

There are several approaches for predicate dispatch, you may want to google for them. But none of them go substantially beyond option (b), they only provide different predefined sets of predicates...


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
.



Relevant Pages

  • Re: newbie: local functions
    ... I'm having a blast trying to memorize the different equality ... > predicates in CL. ... ever use EQ instead of EQL. ... Lisp is the red pill. ...
    (comp.lang.lisp)
  • Re: newbie: local functions
    ... I'm having a blast trying to memorize the different equality ... >> predicates in CL. ... > ever use EQ instead of EQL. ...
    (comp.lang.lisp)