Cover image by Dennis Skley on Flickr
Functional programming techniques seem to be rather popular these days. People are using monads in JavaScript, write compilers in OCaml and even hardcore object-oriented languages like Java now support closures.
Wouldn't it be nice if we could use some of the higher-level abstractions, like pattern matching, in omnipresent languages like JavaScript?
There is an TC39 proposal for new syntax that enables this feature, but it just stage-1 and didn't see updates for nine months.
Luckily for us, there is a library called Z that lets us pattern match without the need for additional syntax.
Why
Pattern matching is a switch on steroids; you can create powerful conditions such based on Object properties or Array content without manipulating the Object or Array itself. That amount of power leads you to write functional, immutable, and expressive code instead imperative, which reduces a lot of complexity and bugs.
What
Z is a JavaScript library that allows us to use pattern matching in JavaScript without the need for new syntax. We install an NPM package and are ready to go!
How
The Z package exports a matches
function we can use like we would use if
or switch
.
One main difference is, matches returns the case that matched, so it behaves like an expression instead of a statement. If nothing matched, it will return undefined
.
So, what can it do?
Like switch
it can match by value.
const result = matches(x)(
(c = 1) => "One!",
(c = 2) => "Two!",
(c) => "Something different..."
);
But, unlike switch
, it can also match more complex values.
const result = matches(x)(
(c = {data: 123}) => "We got data!",
(c = {error: 404}) => "We got an error!",
(c = [1,2,3]) => "We got an array!"
);
It's also possible to match by type.
const result = matches(o)(
(c = Date) => "We got the date " + c.toString(),
(c = Number) => "We got the number " + c,
(c = Array) => "We got an array!"
);
We can also use it to destructure arrays or expect arrays with a specific length.
const result = matches(["hello", ",", "world", "!"])(
(first, tail) => first + tail.join(""),
(first, tail = []) => "Array only has one element!"
);
Conclusion
Z uses standard JavaScript syntax, but it plays some tricks here. Seemingly it compares our value with the default values of our callback functions. This decision leads to the unusual usage of the =
operator instead of the ==
and ===
operators.
It also seems to be planned to make a strict matching mode, that throws an error instead of returning undefined if a check wasn't exhaustive.
While I don't know if this is the best way to implement pattern matching in JavaScript it's at least an interesting one and could help to prevent some errors while leading to more concise code.
Tell me what do you think in the comments :)
If you like my posts, you can also follow me on Twitter!