Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Common Lisp user-defined type in defmethod

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?

like image 319
user3414663 Avatar asked Dec 19 '22 04:12

user3414663


2 Answers

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.

like image 161
Xach Avatar answered Feb 07 '23 13:02

Xach


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.

like image 34
user3414663 Avatar answered Feb 07 '23 11:02

user3414663