Skip to content
Masataro Asai edited this page Mar 27, 2015 · 6 revisions

Trivia maintains a full compatibility with Optima. If you are already familier with Optima, there is no need to understand anything new, other than the additional patterns introduced in Trivia. As the baseline, this page describe the syntax of macro match and its variants. In the following sections, I briefly summarize what kind of patterns are available in these matcher macros.

Type-based Destructuring Patterns

This section contains standard, object-accessing patterns that are most commonly used.

Cons Pattern

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)

List, List* Pattern

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))

Both patterns can be derived from cons pattern. See also: ./defpattern

Vector, Vector* Patterns

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)

Class Pattern

Syntax
class type &rest slot-descriptions

structure type &rest slot-descriptions

slot-descriptions
either of the following:
  • make-instance style plist : {keyword subpattern}*
  • with-slots style : (slot-name subpattern)*
  • names as the variables : slot-name*

structure pattern is just a synonym to the class pattern.

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

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.

Assoc, Property, Alist, Plist Pattern

Syntax
assoc item subpattern &key key test

property key subpattern &optional default

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.

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.

Logic Patterns

And, Or pattern

Syntax
and &rest subpattterns

or &rest subpattterns

They matches when all/some of the subpatterns matches against the element. For example,

(match x
  ((or (list 1 a)
       (cons a 3))
   a))

matches against both (1 2) and (4 . 3) and returns 2 and 4, respectively. Also,

(match x
  ((and (list 1 _)
        (list _ 2))
   t))

is same as below.

(match x
  ((list 1 2)
   t))

Not pattern

Syntax
not subpattern

It does not match when subpattern matches. The variables used in subpattern is not visible in the body.

Guard pattern

Syntax
guard subpattern1 test-form {generator-form subpattern2}*
test-form
a predicate form, evaluated.
generator-form
a form that produce a value, which are then matched against the next subpattern2.

The object is first matched against subpattern1. If that fails, whole clause declines the matching. Otherwize, test-form is evaluated. When the result is true, then each of generator-form is evaluated and matched against corresponding subpattern2.

Example:

(match (list 2 5)
  ((guard (list x y)     ; subpattern
          (= 10 (* x y)) ; test-form
          (- x y) (satisfies evenp)) ; generator1, subpattern1
   t))
;; --> nil, since (- x y) == 3 does not satisfies evenp

Special Patterns

This section contains patterns that has specific roles in itself.

Place Pattern

Syntax
place subpattern

The subpattern is accessed by symbol-macrolet instead of let.

Example:

(defvar *x* (list 0 1))
(match *x*
  ((list (place x) y)
   (setf x :success)
   (setf y :fail)))

(print *x*)
;; --> (:SUCCESS 1)

Bind Pattern

Syntax
<> pattern value &optional var

The current matching value is bound to var. The result of evaluating value using var is then matched against pattern. var is optional and can be omitted when value is a constant and does not need the current matching value.

This is important when you write a defpattern that has a default value. Consider writing a pattern that matches against both of 'string and '(string *) and has a subpattern length. length should be bound to '* even when the input is 'string. With <> pattern, it can be implemented as below.

(defpattern string-type-specifier (length)
   `(or (list 'string ,length)
        (and 'string (<> ,length '*))))

Access Pattern

Just want to access an element? It’s time to use access pattern:

Syntax
access #’accessor subpattern
Syntax
access ‘accessor subpattern
accessor
a function name.

The object is not checked. The value of funcall ing the current object is matched against subpattern.

Example:

(match '((1 2 (3 4)) 5 (6))
  ((access #'flatten (list* _ _ 3 _))))