If a type specifier is a list, the car of the list is a symbol, and the rest of the list is subsidiary type information. In many cases a subsidiary item may be unspecified. The unspecified subsidiary item is indicated by writing *. For example, to completely specify a vector type, one must mention the type of the elements and the length of the vector, as for example
To leave the length unspecified, one would write
To leave the element type unspecified, one would write
One may also leave both length and element type unspecified:
Suppose that two type specifiers are the same except that the first has a * where the second has a more explicit specification. Then the second denotes a subtype of the type denoted by the first.
array | fixnum | package | simple-string |
atom | float | pathname | simple-vector |
bignum | function | random-state | single-float |
bit | hash-table | ratio | standard-char |
bit-vector | integer | rational | stream |
character | keyword | readtable | string |
list | sequence | ||
compiled-function | long-float | short-float | symbol |
complex | nil | signed-byte | t |
cons | null | simple-array | unsigned-byte |
double-float | number | simple-bit-vector | vector |
As a convenience, if a list has one or more unspecified items at the end, such items may simply be dropped rather than writing an explicit * for each one. If dropping all occurrences of * results in a singleton list, then the parentheses may be dropped as well (the list may be replaced by the symbol in its car). For example, (vector double-float *) may be abbreviated to (vector double-float), and (vector * *) may be abbreviated to (vector) and then to simply vector.