The less-familiar parts of Lisp for beginners — deftype

Moving onwards, the casual Lisp programmer arriving from C++ might not have encountered deftype in his or her reading.  There’s a fine description and example of the macro in the CLHS.  This macro allows the programmer to define a new type specifier.

So, why might the programmer want to create new type specifiers?  Most commonly, programmers either want to use them along with declare and the to provide compiler hints, helping the optimizer to know what underlying types are being used.  The programmer-defined type specifier is somewhat similar to a C++ typedef, by defining your own type specifier you can easily alter code when you have to change the underlying type, without having to search through your code for occurrences of the type.

New type specifiers also might be useful in typecase statements:
 

(defun equidimensional (a)
  (or (< (array-rank a) 2)
      (apply #'= (array-dimensions a))))

(defun all-ints (a)
  (let ((len (array-total-size a)))
    (dotimes (i len)
      (unless (integerp (row-major-aref a i))
        (return-from all-ints nil)))
    t))

(deftype square-matrix (&optional type size)
  `(and (array ,type (,size ,size))
        (satisfies equidimensional)))

(deftype integer-square-matrix (&optional size)
  `(and (square-matrix integer ,size)
        (satisfies all-ints)))

(defun demonstrate ()
  (let ((objects (list :ABC
                       (make-array '(2 3))
                       (make-array '(2 2) :initial-element 1)
                       (make-array '(2 2) :initial-element 1.1))))
    (dolist (obj objects)
      (format t "~S~26T" obj)
      (typecase obj
        (integer-square-matrix
         (format t "is an integer square matrix"))
        (square-matrix
         (format t "is a square matrix"))
        (array
         (format t "is a non-square matrix"))
        (t
         (format t "is a non-matrix")))
      (format t "~%"))))

Producing output:
 
CL-USER> (demonstrate)
:ABC                      is a non-matrix
#2A((0 0 0) (0 0 0))      is a non-square matrix
#2A((1 1) (1 1))          is an integer square matrix
#2A((1.1 1.1) (1.1 1.1))  is a square matrix
NIL

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

反垃圾邮件 / Anti-spam question * Time limit is exhausted. Please reload CAPTCHA.