tags:

views:

51

answers:

1

I would like to define a type specifier that describes a list of things of the same type. So I would like to have (list-of integer) similar to (array integer) (which is built-in). I am able to create it for a specific type, like this:

(defun elements-are-integer (seq) 
  (every #'(lambda (x) (typep x 'integer)) seq))
(deftype list-of-integer ()
  '(and list (satisfies elements-are-integer)))

However, this means I have to do this for every possible type. How can I change this code so that the type would take another type as an argument, and construct the satisfies predicate on the fly? The problem is that the satisfies requires a global symbol, and I don't know how to define the predicate function in proper context (I guess I need to gensym it somehow, but how?). Also, the solution should work so that the type could be created inside another package.

A: 

I must confess I don't know common lisp enough to understand exactly what deftype is used for, but this macro should do it...

(defmacro deftype-list-of (type)
  (let* ((etfname (intern (concatenate 'string "ELEMENTS-ARE-"
                                       (symbol-name type))))
         (ltname (intern (concatenate 'string "LIST-OF-"
                                      (symbol-name type))))
         (tcdef `(defun ,etfname (seq)
                   (every (lambda (x) (typep x ',type)) seq)))
         (ltdef `(deftype ,ltname ()
                   '(and list (satisfies ,etfname)))))
    (if (fboundp etfname)
        ltdef
        `(progn ,tcdef ,ltdef))))

For example (deftype-list-of integer) expands to code equivalent to the one you posted.

This code defines the type in the current package (I suppose), but changing it to allow accepting a package name should be trivial.

6502
Thanks. It's definitely useful, even though it isn't what I exactly wanted.
J S