'Expand eql clause of a defmethod statement to accept any function?

A few days ago, I learned about the eql clause of the defmethod argument specification syntax. The defmethod hyperspec makes it clear that the presence of the eql token is a fundamental part of the syntax. For instance, I get an error when I try the following in CLISP:

(defgeneric q (a))

(defmethod q ((a (eql 0)))                  ;standard eql clause syntax, all is well
     (print "Method called with eql a 0"))

(defmethod q ((a (< 0)))                    ;trying to use < instead of eql
     (print "Method called with < 0 a"))


;=> *** - DEFMETHOD Q: Invalid specializer (< 0) in lambda list ((A (< 0)))

(< is a bad example here as it only works on numbers, but you hopefully get my point)

I was confused (and still am) regarding why eql is the only function allowed in this syntax, but as I doubt this has a definitive answer beyond "The developers made it that way" I won't make that the point of this question.

Is there any way to work around this limitation of the eql clause and force defmethod to test arbitrary functions against its arguments? i'm looking for a functionality somewhat similar to guards in Haskell, eg, the above example (if it worked) should behave like:

q a
    | a == 0 = putStrLn "Method called with eql 0 a"
    | 0 < a = putStrLn "Method called with < 0 a"


Solution 1:[1]

The EQL mechanism is there to allow dispatch to work on individual objects.

Allowing arbitrary predicates for dispatch is not a part of standard Common Lisp. It's also not trivial to make it fit into CLOS dispatch.

The Haskell part is not comparable, since Generic Functions in Common Lisp are an object-oriented mechanism (with multi-dispatch, inheritance and method combinations) and work different.

What you are looking for is called Predicate Dispatch.

Extensions exist. See: http://common-lisp.net/project/closer/filtered.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1