├── .gitignore ├── README.markdown ├── src ├── combinators.lisp ├── designators.lisp ├── lists.lisp ├── package.lisp ├── specials.lisp ├── streams.lisp └── typespecs.lisp └── trivial-types.asd /.gitignore: -------------------------------------------------------------------------------- 1 | *.fasl 2 | *.dx64fsl 3 | *.dx32fsl 4 | *.lx64fsl 5 | *.x86f 6 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | trivial-types - Trivial type definitions 2 | ======================================== 3 | 4 | TRIVIAL-TYPES provides missing but important type 5 | definitions such as PROPER-LIST, ASSOCIATION-LIST, PROPERTY-LIST and 6 | TUPLE. 7 | 8 | By using these types, you can keep type declarations more 9 | accurate. For example, you may write a class definition like: 10 | 11 | (defclass person () 12 | ((name :type string)) 13 | ((age :type fixnum)) 14 | ((friends :type list))) 15 | 16 | However, it is not obvious for anyone except you that FRIENDS slot has 17 | only a list of person. If you want declare FRIENDS slot more 18 | accurately, PROPER-LIST is the best for that: 19 | 20 | (defclass person () 21 | ((name :type string)) 22 | ((age :type fixnum)) 23 | ((friends :type (proper-list person)))) 24 | 25 | In addition, TRIVIAL-TYPES also provides standard designators defined 26 | in ANSI standard such as PACKAGE-DESIGNATOR. They are useful when you 27 | write a function that takes a package-oid argument like: 28 | 29 | (defun list-external-symbols (package) 30 | (declare (package-designator package)) 31 | (loop for symbol being the external-symbol of package 32 | collect symbol)) 33 | 34 | [Package] trivial-types 35 | ----------------------- 36 | 37 | ## [Function] proper-list-p 38 | 39 | proper-list-p object 40 | 41 | Returns true if OBJECT is a proper list. 42 | 43 | Examples: 44 | 45 | (proper-list-p 1) => NIL 46 | (proper-list-p '(1 . 2)) => NIL 47 | (proper-list-p nil) => T 48 | (proper-list-p '(1 2 3)) => T 49 | 50 | ## [Type] proper-list 51 | 52 | proper-list &optional (element-type '*) 53 | 54 | Equivalent to `(and list (satisfies proper-list-p))`. ELEMENT-TYPE 55 | is just ignored. 56 | 57 | Examples: 58 | 59 | (typep '(1 2 3) '(proper-list integer)) => T 60 | (typep '(1 2 3) '(proper-list string)) => T 61 | 62 | ## [Function] property-list-p 63 | 64 | property-list-p object 65 | 66 | Returns true if OBJECT is a property list. 67 | 68 | Examples: 69 | 70 | (property-list-p 1) => NIL 71 | (property-list-p '(1 2 3)) => NIL 72 | (property-list-p '(foo)) => NIL 73 | (property-list-p nil) => T 74 | (property-list-p '(foo 1)) => T 75 | (property-list-p '(:a 1 :b 2)) => T 76 | 77 | ## [Type] property-list 78 | 79 | property-list &optional (value-type '*) 80 | 81 | Equivalent to `(and list (satisfies 82 | property-list-p))`. VALUE-TYPE is just ignored. 83 | 84 | Examples: 85 | 86 | (typep '(:a 1 :b 2) '(property-list integer)) => T 87 | (typep '(:a 1 :b 2) '(property-list string)) => T 88 | 89 | ## [Function] association-list-p 90 | 91 | association-list-p var 92 | 93 | Returns true if OBJECT is an association list. 94 | 95 | Examples: 96 | 97 | (association-list-p 1) => NIL 98 | (association-list-p '(1 2 3)) => NIL 99 | (association-list-p nil) => T 100 | (association-list-p '((foo))) => T 101 | (association-list-p '((:a . 1) (:b . 2))) => T 102 | 103 | ## [Type] association-list 104 | 105 | association-list &optional (key-type '*) (value-type '*) 106 | 107 | Equivalent to `(proper-list (cons KEY-TYPE VALUE-TYPE))`. KEY-TYPE 108 | and VALUE-TYPE are just ignored. 109 | 110 | Examples: 111 | 112 | (typep '((:a . 1) (:b . 2)) '(association-list integer)) => T 113 | (typep '((:a . 1) (:b . 2)) '(association-list string)) => T 114 | 115 | ## [Function] tuplep 116 | 117 | tuplep object 118 | 119 | Returns true if OBJECT is a tuple, meaning a proper list. 120 | 121 | Examples: 122 | 123 | (tuplep 1) => NIL 124 | (tuplep '(1 . 2)) => NIL 125 | (tuplep nil) => T 126 | (tuplep '(1 2 3)) => T 127 | 128 | ## [Type] tuple 129 | 130 | tuple &rest element-types 131 | 132 | Equivalent to `(and list (cons ARG1 (cons ARG2 (cons ARG3 ...))))` 133 | where ARGn is each element of ELEMENTS-TYPES. 134 | 135 | Examples: 136 | 137 | (typep 1 'tuple) => NIL 138 | (typep '(1 . 2) 'tuple) => NIL 139 | (typep '(1 2 3) 'tuple) => NIL 140 | (typep '(1 2 3) '(tuple integer integer)) => NIL 141 | (typep '(1 2 3) '(tuple string integer integer)) => NIL 142 | (typep nil 'tuple) => T 143 | (typep nil '(tuple)) => T 144 | (typep '(1 2 3) '(tuple integer integer integer)) => T 145 | 146 | ## [Type] character-designator 147 | 148 | character-designator 149 | 150 | ## [Type] function-designator 151 | 152 | function-designator 153 | 154 | ## [Type] file-position-designator 155 | 156 | file-position-designator 157 | 158 | ## [Type] list-designator 159 | 160 | list-designator 161 | 162 | ## [Type] package-designator 163 | 164 | package-designator 165 | 166 | ## [Type] pathname-designator 167 | 168 | pathname-designator 169 | 170 | ## [Type] stream-designator 171 | 172 | stream-designator 173 | 174 | ## [Type] string-designator 175 | 176 | string-designator 177 | 178 | ## [Function] file-associated-stream-p 179 | 180 | file-associated-stream-p stream 181 | 182 | Returns true if STREAM is a stream associated to a file. 183 | 184 | ## [Type] file-associated-stream 185 | 186 | file-associated-stream 187 | 188 | Equivalent to `(and stream (satisfies file-associated-stream-p))`. 189 | 190 | ## [Type] non-nil 191 | 192 | non-nil &optional type 193 | 194 | Equivalent to `(and (not null) TYPE)` if TYPE is given, 195 | otherwise `(not null)`. 196 | 197 | Examples: 198 | 199 | (typep nil '(non-nil symbol)) => NIL 200 | 201 | ## [Function] type-specifier-p 202 | 203 | type-specifier-p type-specifier 204 | 205 | Returns true if TYPE-SPECIFIER is a valid type specfiier. 206 | 207 | ## [Function] type-expand 208 | 209 | type-expand type-specifier &optional env 210 | 211 | Expand TYPE-SPECIFIER in the lexical environment ENV. 212 | 213 | Authors 214 | ------- 215 | 216 | * Tomohiro Matsuyama 217 | 218 | License 219 | ------- 220 | 221 | LLGPL 222 | -------------------------------------------------------------------------------- /src/combinators.lisp: -------------------------------------------------------------------------------- 1 | (in-package :trivial-types) 2 | 3 | (deftype non-nil (&optional type) 4 | "Equivalent to `(and (not null) TYPE)` if TYPE is given, 5 | otherwise `(not null)`. 6 | 7 | Examples: 8 | 9 | (typep nil '(non-nil symbol)) => NIL" 10 | (if type 11 | `(and (not null) ,type) 12 | '(not null))) 13 | -------------------------------------------------------------------------------- /src/designators.lisp: -------------------------------------------------------------------------------- 1 | (in-package :trivial-types) 2 | 3 | (deftype character-designator () 4 | '(or (string 1) 5 | character)) 6 | 7 | (deftype function-designator () 8 | '(or symbol 9 | function)) 10 | 11 | (deftype file-position-designator () 12 | '(or (member :start :end) 13 | (integer 0))) 14 | 15 | (deftype list-designator () 16 | '(or (non-nil atom) 17 | proper-list)) 18 | 19 | (deftype package-designator () 20 | '(or string-designator 21 | package)) 22 | 23 | (deftype pathname-designator () 24 | '(or string 25 | file-associated-stream 26 | pathname)) 27 | 28 | (deftype stream-designator () 29 | '(or (member t nil) 30 | stream)) 31 | 32 | (deftype string-designator () 33 | '(or character 34 | symbol 35 | string)) 36 | -------------------------------------------------------------------------------- /src/lists.lisp: -------------------------------------------------------------------------------- 1 | (in-package :trivial-types) 2 | 3 | (declaim (inline proper-list-p 4 | property-list-p 5 | association-list-p 6 | tuplep)) 7 | 8 | (defmacro %proper-list-p (var &optional (element-type '*)) 9 | `(loop 10 | (typecase ,var 11 | (null (return t)) 12 | (cons (if (or ,(eq element-type '*) 13 | (typep (car ,var) ,element-type)) 14 | (setq ,var (cdr ,var)) 15 | (return))) 16 | (t (return))))) 17 | 18 | (defun proper-list-p (object) 19 | "Returns true if OBJECT is a proper list. 20 | 21 | Examples: 22 | 23 | (proper-list-p 1) => NIL 24 | (proper-list-p '(1 . 2)) => NIL 25 | (proper-list-p nil) => T 26 | (proper-list-p '(1 2 3)) => T" 27 | (declare (optimize . #.*standard-optimize-qualities*)) 28 | (%proper-list-p object)) 29 | 30 | (deftype proper-list (&optional (element-type '*)) 31 | "Equivalent to `(and list (satisfies proper-list-p))`. ELEMENT-TYPE 32 | is just ignored. 33 | 34 | Examples: 35 | 36 | (typep '(1 2 3) '(proper-list integer)) => T 37 | (typep '(1 2 3) '(proper-list string)) => T" 38 | (declare (ignore element-type)) 39 | '(and list (satisfies proper-list-p))) 40 | 41 | (defun property-list-p (object) 42 | "Returns true if OBJECT is a property list. 43 | 44 | Examples: 45 | 46 | (property-list-p 1) => NIL 47 | (property-list-p '(1 2 3)) => NIL 48 | (property-list-p '(foo)) => NIL 49 | (property-list-p nil) => T 50 | (property-list-p '(foo 1)) => T 51 | (property-list-p '(:a 1 :b 2)) => T" 52 | (declare (optimize . #.*standard-optimize-qualities*)) 53 | (typecase object 54 | (null t) 55 | (cons 56 | (loop 57 | (if (null object) 58 | (return t) 59 | (let ((key (car object)) 60 | (next (cdr object))) 61 | (if (or (not (symbolp key)) 62 | (not (consp next))) 63 | (return) 64 | (setq object (cdr next))))))))) 65 | 66 | (deftype property-list (&optional (value-type '*)) 67 | "Equivalent to `(and list (satisfies 68 | property-list-p))`. VALUE-TYPE is just ignored. 69 | 70 | Examples: 71 | 72 | (typep '(:a 1 :b 2) '(property-list integer)) => T 73 | (typep '(:a 1 :b 2) '(property-list string)) => T" 74 | (declare (ignore value-type)) 75 | '(and list (satisfies property-list-p))) 76 | 77 | (defun association-list-p (var) 78 | "Returns true if OBJECT is an association list. 79 | 80 | Examples: 81 | 82 | (association-list-p 1) => NIL 83 | (association-list-p '(1 2 3)) => NIL 84 | (association-list-p nil) => T 85 | (association-list-p '((foo))) => T 86 | (association-list-p '((:a . 1) (:b . 2))) => T" 87 | (declare (optimize . #.*standard-optimize-qualities*)) 88 | (%proper-list-p var 'cons)) 89 | 90 | (deftype association-list (&optional (key-type '*) (value-type '*)) 91 | "Equivalent to `(proper-list (cons KEY-TYPE VALUE-TYPE))`. KEY-TYPE 92 | and VALUE-TYPE are just ignored. 93 | 94 | Examples: 95 | 96 | (typep '((:a . 1) (:b . 2)) '(association-list integer)) => T 97 | (typep '((:a . 1) (:b . 2)) '(association-list string)) => T" 98 | `(proper-list (cons ,key-type ,value-type))) 99 | 100 | (defun tuple (&rest args) 101 | "Exactly same as LIST." 102 | (declare (optimize . #.*standard-optimize-qualities*)) 103 | args) 104 | 105 | (defun tuplep (object) 106 | "Returns true if OBJECT is a tuple, meaning a proper list. 107 | 108 | Examples: 109 | 110 | (tuplep 1) => NIL 111 | (tuplep '(1 . 2)) => NIL 112 | (tuplep nil) => T 113 | (tuplep '(1 2 3)) => T" 114 | (declare (optimize . #.*standard-optimize-qualities*)) 115 | (%proper-list-p object)) 116 | 117 | (deftype tuple (&rest element-types) 118 | "Equivalent to `(and list (cons ARG1 (cons ARG2 (cons ARG3 ...))))` 119 | where ARGn is each element of ELEMENT-TYPES. 120 | 121 | Examples: 122 | 123 | (typep 1 'tuple) => NIL 124 | (typep '(1 . 2) 'tuple) => NIL 125 | (typep '(1 2 3) 'tuple) => NIL 126 | (typep '(1 2 3) '(tuple integer integer)) => NIL 127 | (typep '(1 2 3) '(tuple string integer integer)) => NIL 128 | (typep nil 'tuple) => T 129 | (typep nil '(tuple)) => T 130 | (typep '(1 2 3) '(tuple integer integer integer)) => T" 131 | `(and list 132 | ,(reduce (lambda (element-type type) `(cons ,element-type ,type)) 133 | element-types 134 | :from-end t 135 | :initial-value 'null))) 136 | -------------------------------------------------------------------------------- /src/package.lisp: -------------------------------------------------------------------------------- 1 | (in-package :cl-user) 2 | 3 | (defpackage :trivial-types 4 | (:use :cl) 5 | (:export #:proper-list-p 6 | #:proper-list 7 | #:property-list-p 8 | #:property-list 9 | #:association-list-p 10 | #:association-list 11 | #:tuplep 12 | #:tuple 13 | 14 | #:character-designator 15 | #:function-designator 16 | #:file-position-designator 17 | #:list-designator 18 | #:package-designator 19 | #:pathname-designator 20 | #:stream-designator 21 | #:string-designator 22 | 23 | #:file-associated-stream-p 24 | #:file-associated-stream 25 | 26 | #:non-nil 27 | 28 | #:type-specifier-p 29 | #:type-expand)) 30 | -------------------------------------------------------------------------------- /src/specials.lisp: -------------------------------------------------------------------------------- 1 | (in-package :trivial-types) 2 | 3 | (defvar *standard-optimize-qualities* 4 | '((speed 3) 5 | (safety 0) 6 | (space 0) 7 | (debug 1) 8 | (compilation-speed 0))) 9 | -------------------------------------------------------------------------------- /src/streams.lisp: -------------------------------------------------------------------------------- 1 | (in-package :trivial-types) 2 | 3 | (defun file-associated-stream-p (stream) 4 | "Returns true if STREAM is a stream associated to a file." 5 | (declare (optimize . #.*standard-optimize-qualities*)) 6 | (or (typep stream 'file-stream) 7 | (and (typep stream 'synonym-stream) 8 | (let* ((target-symbol (synonym-stream-symbol stream)) 9 | (target-stream (symbol-value target-symbol))) 10 | (declare (type symbol target-symbol) 11 | (type stream target-stream)) 12 | (file-associated-stream-p target-stream))))) 13 | 14 | (deftype file-associated-stream () 15 | "Equivalent to `(and stream (satisfies file-associated-stream-p))`." 16 | '(and stream (satisfies file-associated-stream-p))) 17 | -------------------------------------------------------------------------------- /src/typespecs.lisp: -------------------------------------------------------------------------------- 1 | (in-package :trivial-types) 2 | 3 | (defun type-specifier-p (type-specifier) 4 | "Returns true if TYPE-SPECIFIER is a valid type specfiier." 5 | (or (documentation type-specifier 'type) 6 | #+sbcl (sb-ext:valid-type-specifier-p type-specifier) 7 | #+openmcl (ccl:type-specifier-p type-specifier) 8 | #+ecl (c::valid-type-specifier type-specifier))) 9 | 10 | (defun type-expand (type-specifier &optional env) 11 | "Expand TYPE-SPECIFIER in the lexical environment ENV." 12 | #+sbcl (sb-ext::typexpand type-specifier env) 13 | #+openmcl (ccl::type-expand type-specifier env) 14 | #-(or sbcl openmcl) type-specifier) 15 | -------------------------------------------------------------------------------- /trivial-types.asd: -------------------------------------------------------------------------------- 1 | (in-package :cl-user) 2 | 3 | (defpackage :trivial-types-asd 4 | (:use :cl :asdf)) 5 | (in-package :trivial-types-asd) 6 | 7 | (defsystem :trivial-types 8 | :description "Trivial type definitions" 9 | :long-description "TRIVIAL-TYPES provides missing but important type 10 | definitions such as PROPER-LIST, ASSOCIATION-LIST, PROPERTY-LIST and 11 | TUPLE. 12 | 13 | By using these types, you can keep type declarations more 14 | accurate. For example, you may write a class definition like: 15 | 16 | (defclass person () 17 | ((name :type string)) 18 | ((age :type fixnum)) 19 | ((friends :type list))) 20 | 21 | However, it is not obvious for anyone except you that FRIENDS slot has 22 | only a list of person. If you want declare FRIENDS slot more 23 | accurately, PROPER-LIST is the best for that: 24 | 25 | (defclass person () 26 | ((name :type string)) 27 | ((age :type fixnum)) 28 | ((friends :type (proper-list person)))) 29 | 30 | In addition, TRIVIAL-TYPES also provides standard designators defined 31 | in ANSI standard such as PACKAGE-DESIGNATOR. They are useful when you 32 | write a function that takes a package-oid argument like: 33 | 34 | (defun list-external-symbols (package) 35 | (declare (package-designator package)) 36 | (loop for symbol being the external-symbol of package 37 | collect symbol))" 38 | :version "0.1" 39 | :author "Tomohiro Matsuyama" 40 | :license "LLGPL" 41 | :components ((:module "src" 42 | :serial t 43 | :components ((:file "package") 44 | (:file "specials") 45 | (:file "lists") 46 | (:file "designators") 47 | (:file "streams") 48 | (:file "combinators") 49 | (:file "typespecs"))))) 50 | --------------------------------------------------------------------------------