Derived Types
Macro: cl-deftype name arglist [docstring] [decls] forms…
This macro defines a new type called name. Types defined this way are called derived types. It is similar to defmacro in many ways; when name is encountered as a type name, the body forms are evaluated and should return a type specifier that is equivalent to the type. The arglist is a Common Lisp argument list of the sort accepted by cl-defmacro. The type specifier ‘(name args…)’ is expanded by calling the expander with those arguments; the type symbol ‘name’ is expanded by calling the expander with no arguments. The arglist is processed the same as for cl-defmacro except that optional arguments without explicit defaults use * instead of nil as the “default” default. Some examples:
(cl-deftype null () '(satisfies null)) ; predefined
(cl-deftype list () '(or null cons)) ; predefined
(cl-deftype unsigned-byte (&optional bits)
(list 'integer 0 (if (eq bits '*) bits (1- (ash 1 bits)))))
(unsigned-byte 8) ≡ (integer 0 255)
(unsigned-byte) ≡ (integer 0 *)
unsigned-byte ≡ (integer 0 *)The last example shows how the Common Lisp unsigned-byte type specifier could be implemented if desired; this package does not implement unsigned-byte by default.
The cl-typecase (see Conditionals) and cl-check-type (see Assertions and Errors) macros also use type names. The cl-map, cl-concatenate, and cl-merge functions take type-name arguments to specify the type of sequence to return. See Sequences.
Contrary to Common Lisp, CL-Lib supports the use of derived types as method specializers. This comes with a significant caveat: derived types are much too flexible for Emacs to be able to automatically find out which type is a subtype of another, so the ordering of methods is not well-defined when several methods are applicable for a given argument value and the specializer of one or more of those methods is a derived type. To make the order more well-defined, a derived type definition can explicitly state that it is a subtype of others using the decls argument:
(cl-deftype unsigned-byte (&optional bits)
(list 'integer 0 (if (eq bits '*) bits (1- (ash 1 bits)))))
(cl-deftype unsigned-8bits ()
"Unsigned 8-bits integer."
(declare (parents unsigned-byte))
'(unsigned-byte 8))