6

I'd like to be able to use a defined type as a parameter specializer to a defmethod. The motivation is readability and flexibility to change at a later stage. Somehting like this:

(deftype foo () 'fixnum)

(defmethod bar ((x foo)) ...)

(defmethod baz ((x foo)) ...)

However this doesn't work. CLtL2 says "The form deftype does not create any classes."

So I have to write:

(defmethod bar ((x fixnum)) ...)

(defmethod baz ((x fixnum)) ...)

An alternative would be to define a class called foo which is nothing more than a wrapper around fixnum but wouldn't that be an unacceptable overhead for something so simple as a fixnum?

Is there a better way?

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
user3414663
  • 531
  • 3
  • 11
  • 2
    CLtL2 is outdated. Please use the Common Lisp HyperSpec [CLHS](http://www.lispworks.com/documentation/HyperSpec/Front/Contents.htm), which is based on the ANSI Common Lisp standard. – Rainer Joswig Apr 26 '15 at 13:43
  • CLHS says of `paramet-specializer-names` of `defmethod`: _If parameter-specializer-name is a symbol it names a class_ – user3414663 Apr 26 '15 at 16:38
  • 1
    In fact CLHS also says _The operator deftype does not create any classes._ – user3414663 Apr 26 '15 at 17:29

2 Answers2

12

Methods don't specialize on types, they specialize on classes, or EQL. This is partly the case because an object may be of many types (e.g. the integer 1 is a FIXNUM, a BIT, an UNSIGNED-BYTE, etc.) and it's not obvious how to decide precedence.

If you want less overhead and user-defined abstractions for types, TYPECASE or ETYPECASE may work better than generic functions and methods.

Xach
  • 11,774
  • 37
  • 38
4

The best solution I have been able to find is using filtered dispatch.

Something like this:

(define-filtered-function bar (x)
  (:filters (:foo (typep x 'foo))))

(defmethod bar :filter :foo (x) ...)

However I may resort to Xach's suggestion if the overhead for using this turns out to be too high.

user3414663
  • 531
  • 3
  • 11