blob: 994f2e90eecd09873b2d2b8927db4b9712d52958 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
;;;; petty-types.lisp
(in-package #:petty-types)
(defun type-specifier-p (thing)
"Returns T if THING is a valid TYPE-SPECIFIER, otherwise returns NIL."
(ignore-errors
(typep nil thing)
t))
(deftype type-specifier ()
'(satisfies type-specifier-p))
(defun sequence-of-predicate-for (cont type &optional len)
"Returns the name of a predicate that checks whether its argument is a
sequence of type CONT whose values are all of type TYPE."
(check-type type type-specifier "A TYPE-SPECIFIER")
(check-type cont type-specifier "A TYPE-SPECIFIER")
(assert (subtypep cont 'sequence) (cont) "~s is not a subtype of SEQUENCE." cont)
(check-type cont symbol "A SYMBOL")
(assert (or (eq len '*) (typep len 'fixnum)) (len) "LEN must be '* or a fixnum")
(let ((name
(apply #'a:symbolicate cont :-of- (write-to-string len) :- (a:flatten type)))
(len
(when (typep len 'fixnum)
len)))
(prog1 name
(unless (fboundp name)
(setf (symbol-function name)
(let ((is-type (lambda (xs) (typep xs type))))
(lambda (xs)
(and (typep xs cont)
(or (not len) (= len (length xs)))
(every is-type xs)))))))))
(deftype list-of (type &optional len)
"Type specifier for lists all of the same TYPE."
`(satisfies ,(sequence-of-predicate-for 'list type len)))
(deftype vector-of (type &optional len)
"Type specifier for vectors all of the same TYPE."
`(satisfies ,(sequence-of-predicate-for 'vector type len)))
(deftype optional (type)
"Type specifier for an optional type."
`(or null ,type))
|