Jan 12, 2011

In my post about unification vs. pattern matching I included a little footnote about how the creator of Matchure is probably often asked how pattern matching differs from Clojure’s destructuring. This footnote was an attempt to draw the elusive author out and comment on the subject. Since my attempt was a failure, I decided to throw this post together to explain1 it myself.

Imagine that you have a vector of numbers:

(def $ [1 2 3 4 5])

How might we bind a variable x to the number at the center of this vector? With destructuring this is simple:

(let [[_ _ x _ _] $] x) ;=> 3

However, what if you wanted to bind x based on the precise contents of the vector?

(when-let [[1 2 x 4 5] $] x) ; java.lang.Exception: Unsupported binding form: 1

We can’t do that with destructuring because it only cares about the “shape” or “outline” of the collection. However, using pattern matching we can indeed match in specific cases:

(when-match [[1 2 ?x 4 5] $] x) ;=> 3 (when-match [[1 2 ?x 400 500] $] x) ;=> nil

This is matching at its most precise, but Matchure also allows matching based on arbitrary functions:

(when-match [[(odd? ?) (even? ?) ?x _ _] $] x) ;=> 3 (when-match [[(even? ?) (odd? ?) ?x _ _] $] x) ;=> nil (when-match [[_ _ ?x & (some #{5} ?)] $] x) ;=> 3 (when-match [[_ _ ?x & (some #{42} ?)] $] x) ;=> nil

Both destructuring and pattern matching let you draw a picture of the structure under observation and create bindings as a result. However, pattern matching subsumes destructuring because it allows you to draw at a finer levels of detail.

:F