Pattern Matching — Twice as robust in half the code

Orion Kindel
3 min readAug 2, 2020

Who should read this article?

People who are curious about Functional Programming, Declarative Programming, or want to supercharge their code! 🚀

At the end, there’s a special syntax for Javascript & Typescript that you may not be aware of (hint: I wrote a pattern-matching library @matchbook/ts)

What Pattern Matching is

First, the definition from Wikipedia:

In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern. In contrast to pattern recognition, the match usually has to be exact: “either it will or will not be a match.”
Wikipedia

Practically speaking, you can replace “a given sequence of tokens” with “a given piece of data,” and “some pattern” with “some particular quality or state,” giving us:

In computer science, pattern matching is the act of checking a given piece of data for the presence of […] some particular quality or state.

At risk of being reductive, here’s what this boils down to most of the time in practice:

“Pattern matching is a construct that lets you handle Polymorphic data in a Declarative way.”

Let’s first cover what I mean by “Polymorphic data” and “Declarative

Recap: Polymorphic Data

Sometimes in Programming, we want to solve a problem for multiple types of data at once, so that our code follows the Robustness principle, and is useful in as many contexts as possible.

Data that may be in one of several states, or shapes, is referred to as Polymorphic. (poly — many, morph — shape)

A common example is Shapes; a Triangle , Square , and Circle are all shapes with a calculable area, so a function like function getArea(shape: Shape): number; would be more robust than a getArea function for each subtype.

That’s not to say a function getArea(c: Circle): number; would not be valuable — just less robust.

Recap: Declarative code

In computer science, declarative programming is a programming paradigm […] that expresses the logic of a computation without describing its control flow.

Wikipedia

Code that is Declarative describes the work to be done, and leaves how up to the individual parts.

Contrast this against Imperative Programming, which reads like a step-by-step recipe for the computer to follow.

You may have heard something to the effect of “Declarative Programming means Functional Programming” and “Imperative Programming means Object-Oriented.”

This is an observation, not a rule. You can absolutely write C# code that is very declarative, just as you can write imperative code in Haskell.

The problem Pattern Matching solves

Pattern matching is the Declarative counterpart to if, else, and switch statements.

It allows you to handle conditions and polymorphism, without having to tell the computer how to tell when the conditions are met.

Pattern Matching by example

Case Studies

Let’s explore some concrete examples in a few languages — in each example we declare a Coin type that can be a Penny, Nickel, Dime, or Quarter.

We also declare a function that accepts a Coin and returns its value in dollars, represented by a floating-point number.

Rust

F#

C#

Typescript — switch

Typescript — @matchbook/ts

@matchbook/ts — Robust Pattern Matching in Javascript & Typescript

You may have noticed I snuck something in the last example that is not a language feature, but a library called @matchbook/ts

@matchbook/ts is a Pattern Matching library I wrote that I encourage you to try out, if you’re curious about Pattern Matching and are working in a Javascript or Typescript project 😄

For the trivial example above, it’s actually more verbose than a switch case (although the syntax is much less obtuse IMO) but real code tends not to fit neatly into switch/case statements.

@matchbook/ts is capable of matching on data in way more ways than a switch/case; namely:

  • Based on value match(10, ...)
  • Based on partial structure match({name: 'Bob'}, ...)
  • Based on predicate (type predicates, too!) match(isDog, ...) (isDog is a function of type IsDog :: Animal -> bool)
  • Based on constructor match(Dog, ...) (Dog is a class)

Check it out, let me know what you think!

Afterword

This is my first Medium article, so I invite any & all feedback in the comments — I don’t think this will be the last!

--

--

Orion Kindel

Advocating for quality, user experience, and thoughtful design in code and in products!