In ANSI Common Lisp, by Paul Graham, page 234, there is an example type specifier :
(deftype multiple-of (n)
`(and integer (satisfies (lambda (x)
(zerop (mod x ,n))))))
Unfortunately it seems to not be a valid ANSI Common Lisp as CLHS says SATISFIES only takes a symbol, it can't take a lambda :
CL-USER> (typep 12 '(multiple-of 4))
The SATISFIES predicate name is not a symbol: (LAMBDA (X)
(ZEROP
(MOD X 4)))
[Condition of type SIMPLE-TYPE-ERROR]
How can you create that (multiple-of n)
type specifier ?
Update
More globally, how could you create a type specifier like (integer * *) that can optionally takes two or more parameters and run a function/lambda on it ?
Based on this excellent answer, here is how to implement MULTIPLE-OF type specifier :
(defun make-mof (n)
#'(lambda (x) (zerop (mod x n))))
(defvar *mof-name-cache* (make-hash-table :test #'equal))
(deftype multiple-of (n)
(let ((predicate-name
(or (gethash n *mof-name-cache*)
(let ((pn (make-symbol (with-standard-io-syntax
(format nil "MULTIPLE-OF-~S" n)))))
(setf (symbol-function pn) (make-mof n)
(gethash n *mof-name-cache*) pn)))))
`(satisfies ,predicate-name)))
and now I can check the type like this:
CL-USER> (typep 12 '(multiple-of 4))
T
CL-USER> (typep 13 '(multiple-of 4))
NIL