-
Notifications
You must be signed in to change notification settings - Fork 21
Type based Destructuring Patterns
This section contains standard, object-accessing patterns that are most commonly used.
- Syntax
- cons cdr car
cons
checks if the object is of type cons
, and then matches its
subpatterns with car
and cdr
of that cons cell.
(match '(1 2 3)
((cons x y)
(print x)
(print y)))
;; |-> 1
;; |-> (2 3)
- Syntax
- 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
returns 3
.
(match '(1 2 . 3)
((list* _ _ x)
x))
When list*
pattern has a single subpattern x
e.g. (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
- Syntax
- 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)
structure
pattern is just a synonym to the class
pattern.
- Syntax
- class class-name &rest slot-description*
structure class-name &rest slot-description*
- class-name
- 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.
-
- slot-description
- one of the following:
- make-instance style plist
- keyword subpattern
- with-slots style
- (slot-name subpattern)
- with-accessors style
-
(accessor-name subpattern) .
accessor-name
is 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)
- slot-name
- the value returned by
(slot-value <obj> '<slot-name>)
is bound to the variable of the same name. - accessor-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)))
- Syntax
- type type
satisfies predicate
- type
- type specifier, not evaluated.
- predicate
- 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.
- Syntax
- 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.
- Syntax
- alist &rest args
plist &rest args
alist
and plist
patterns expand into a collection of assoc
and
property
patterns, respectively, connected by an and
pattern.
- Syntax
- 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.
-
CONTENTS
is 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. -
DIMENSIONS
should 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. ’
-
RANK
should be an integer (e.g. 3) or a variable pattern (e.g. A, _). - The rank of the array should be deduced from
DIMENSIONS
orRANK
itself, and the deduced rank and the specifiedRANK
should be consistent when both are present. Otherwise, the compilation fails. Rank information is used to parse the subpatterns. -
TOTAL-SIZE
should be consistent withDIMENSIONS
when all dimensions are fully specified (e.g. whenDIMENSIONS
= ’(5 4 4)
andTOTAL-SIZE
is a variable pattern, then it is bound to 80. WhenTOTAL-SIZE
is an integer, it should be 80 or it signals an error.) -
ELEMENT-TYPE
is*
unless specified. - If
ADJUSTABLE
,HAS-FILL-POINTER
,DISPLACED-TO
are allNIL
, then it is aSIMPLE-ARRAY
. Otherwise it’s anARRAY
.
- Syntax
- 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.
- Syntax
- row-major-array &key element-type adjustable has-fill-pointer displaced-to displaced-index-offset dimensions rank total-size contents
Same as
ARRAY
pattern, but it uses row-major-array to access the elements.CONTENTS
is a list of patterns (just like inVECTOR
pattern), rather than a matrix notation of the patterns in ARRAY pattern.”
For a quickstart, go to the Basics section. Below is for the people already familiar with Optima.