Type based Destructuring Patterns
This section contains standard, object-accessing patterns that are most commonly used.
- cons cdr car
cons checks if the object is of type
cons, and then matches its
cdr of that cons cell.
(match '(1 2 3) ((cons x y) (print x) (print y))) ;; |-> 1 ;; |-> (2 3)
List, List* Pattern
- list &rest subpatterns
list* &rest subpatterns
Both patterns checks if the object is of type
list, has the same length and then matches the contents to the subpatterns.
list* also checks the elements against the subpatterns, however the
last pattern is matched against
nthcdr of the list. Thus, the code below
(match '(1 2 . 3) ((list* _ _ x) x))
list* pattern has a single subpattern
(list* x), however, the object type is not checked and the object always matches. This is related to the definition of list* in http://clhs.lisp.se/Body/f_list_.htm:
If list* receives only one object, that object is returned, regardless of whether or not it is a list.
Pattern matching/destructuring is a dual operation of object construction. If a vector is created with a constructor form
(vector 1 2 3), the pattern which matches the object should also resemble the form, e.g.
(vector a b c). Since destructor & constructor are dual, it is better if the behavior of the pattern reflects the original function.
Both patterns can be derived from
cons pattern. See also: ./defpattern
Vector, Vector* Patterns
- vector &rest subpatterns
vector* &rest subpatterns
vector checks if the object is a vector, if the lengths are the same, and
if the contents matches against each subpatterns.
vector* is similar, but
called a soft-match variant that allows if the length is
larger-than-equal to the length of subpatterns.
(match #(1 2 3) ((vector _ x _) x)) ;; -> 2 (match #(1 2 3 4) ((vector _ x _) x)) ;; -> NIL : does not match (match #(1 2 3 4) ((vector* _ x _) x)) ;; -> 2 : soft match.
There are several specialized subpatterns for vector/vector*. Using these variants properly will results in faster code.
<vector-pattern> : vector | simple-vector bit-vector | simple-bit-vector string | simple-string base-string | simple-base-string | sequence (<vector-pattern> &rest subpatterns)
Class Pattern / Structure Pattern
structure pattern is just a synonym to the
- class class-name &rest slot-description*
structure class-name &rest slot-description*
- A symbol which satisfies one of the following:
(find-class <class-name>)returns a class.
- Symbol <class-name>-p in the same package is fbound. It should be a unary function, or the consequence is undefined.
- Symbol <class-name>p in the same package is fbound. It should be a unary function, or the consequence is undefined.
- one of the following:
- make-instance style plist
- keyword subpattern
- with-slots style
- (slot-name subpattern)
- with-accessors style
(accessor-name subpattern) .
accessor-nameis a symbol, where the corresponding accessor function should be fbound to one of the following symbols:
- Symbol accessor-name itself. (common style for generic functions)
- Symbol <class-name>-<accessor-name> in the same package. (common style for structure accessor functions)
- Symbol <class-name><accessor-name> in the same package. (compatibility to Optima)
- the value returned by
(slot-value <obj> '<slot-name>)is bound to the variable of the same name.
- the value returned by the accessor is bound to the variable of the same name.
We just post an example for each of three style here.
(defstruct foo bar baz) (defvar *x* (make-foo :bar 0 :baz 1) (match *x* ((foo :bar a :baz b) ;; make-instance style (values a b)) ((foo (bar a) (baz b)) ;; with-slots style (values a b)) ((foo bar baz) ;; slot name (values bar baz)))
Type Pattern, Satisfies Pattern
- type type
- type specifier, not evaluated.
- a name of a boolean function of 1 argument, not evaluated.
type pattern matches if the object is of type.
satisfies matches if
the predicate returns true for the object.
lambda form is acceptable.
Assoc, Property, Alist, Plist Pattern
- assoc item subpattern &key key test
property key subpattern &optional default foundp
All these patterns first checks if the pattern is a list. If that is
satisfied, it then obtain the contents with
(cdr (assoc item X key test))
(assoc pattern) or
(getf key X) (property pattern) where X is bound the container. The value
obtained by these accessors is then matched against subpattern.
Property pattern matches the default value to the pattern if supplied and the value was not found, and also binds t/nil to foundp.
Two patterns are derived from these patterns.
- alist &rest args
plist &rest args
plist patterns expand into a collection of
property patterns, respectively, connected by an
Array, simple-array, row-major-array pattern
- array &key element-type adjustable has-fill-pointer displaced-to (displaced-index-offset 0) dimensions rank total-size (contents nil)
Matches against an array, its contents, and its meta-level information such as size, element-type.
CONTENTSis a matrix notation of patterns, i.e., a tree of patterns. For example,
:contents ((A _ _) (_ B _) (_ _ C))matches against
(AREF X 0 0),
(AREF X 1 1),
(AREF X 2 2)of an array X and binds them to A, B, C respectively.
DIMENSIONSshould be either
- a quoted list of integers (e.g. ’
(5 4 4)),
- an integer specifying a 1-dimensional array (e.g. 256),
- or a list pattern (e.g.
(list 5 A _)).
- a quoted list of integers (e.g. ’
RANKshould be an integer (e.g. 3) or a variable pattern (e.g. A, _).
- The rank of the array should be deduced from
RANKitself, and the deduced rank and the specified
RANKshould be consistent when both are present. Otherwise, the compilation fails. Rank information is used to parse the subpatterns.
TOTAL-SIZEshould be consistent with
DIMENSIONSwhen all dimensions are fully specified (e.g. when
(5 4 4)and
TOTAL-SIZEis a variable pattern, then it is bound to 80. When
TOTAL-SIZEis an integer, it should be 80 or it signals an error.)
NIL, then it is a
SIMPLE-ARRAY. Otherwise it’s an
- simple-array &key element-type dimensions rank total-size contents
Matches against a simple-array, its contents, and its meta-level information such as size, element-type. This is a wrapper around the base ARRAY pattern.
- row-major-array &key element-type adjustable has-fill-pointer displaced-to displaced-index-offset dimensions rank total-size contents
ARRAYpattern, but it uses row-major-array to access the elements.
CONTENTSis a list of patterns (just like in
VECTORpattern), rather than a matrix notation of the patterns in ARRAY pattern.”