Skip to content
David Nolen edited this page Jun 17, 2013 · 18 revisions

Matching Literals

The simplest thing you can do is match literals:

(let [x true
      y true
      z true]
  (match [x y z]
    [_ false true] 1
    [false true _ ] 2
    [_ _ false] 3
    [_ _ true] 4
    :else 5))

Note that the only clause that matches the values of the local variables is the fourth one. "Wildcards", the _, in the pattern signifies values that are present that you don't actually care about.

When matching on a single variable you may omit the brackets:

(let [x true]
  (match x
    true 1
    false 2
    :else 5))

Binding

You may match values and give them names for later use:

(let [x 1 y 2]
  (match [x y]
    [1 b] b
    [a 2] a
   :else nil))

This may seem pointless here but in complex patterns this feature becomes more useful (consider red black tree balancing for example).

Sequential types

You may match sequences by using the sequence matching facility:

(let [x [1 2 nil nil nil]]
  (match [x]
    [([1] :seq)] :a0
    [([1 2] :seq)] :a1
    [([1 2 nil nil nil] :seq)] :a2
    :else nil))

Note this works on all ISeqs as well as Sequential types.

Vector types

You can also match vector types, the benefit is much better performance when you want to test something internal without looking at earlier values - random access:

(let [x [1 2 3]]
  (match [x]
    [[_ _ 2]] :a0
    [[1 1 3]] :a1
    [[1 2 3]] :a2
    :else :a3))

core.match will optimize this case and test the third column first.

Rest patterns

Both seq and vector patterns support rest patterns. As in Clojure's builtin destructuring, rest pattern will capture the "rest" of a collection.

Map patterns

Or patterns

Guards

Clone this wiki locally