match
Pattern matching algorithm
Install
Install with npm
$ npm i -S @mattstyles/match
Example
const match = require('@mattstyles/match')
Usage
Match
implements a simple pattern matching mechanism, heavily inspired by Rust’s match keyword.
const match = require('@mattstyles/match')
const log = prefix => value => console.log(`${prefix}${value}`)
const matcher = match([
['FOO', log('::')],
['BAR', log('> ')]
])
matcher('FOO')
// ::FOO
matcher('BAR')
// > BAR
Match
can be used to simplify complex branching logic and if/then
soup.
Matching on all the things
Match
will attempt a strict equality check (===
) on your match conditions which means that strings and integers are trivial to use, even matching on the same object is possible as match accepts an array of tuples of the form <any, function>.
const obj = {foo: 'bar'}
const matcher = match([
['FOO', log()],
[23, log()],
[obj, log()]
])
// Even this would match
matcher(obj)
The wise will know that JS pattern matching capabilities and type system aren’t particularly helpful to our goal and the eagle eyed will notice that in the above example it will only match against the exact same object, not an instance that merely looks identical.
Thankfully JS isn’t totally hapless and many problems can be solved by the humble function (sometimes at the expense of brevity or clarity). Match
can accept a predicate function to use as a match condition:
const deepEqual = require('deep-equal')
const equal = predicate => value => deepEqual(predicate, value)
const matcher = match([
[equal({foo: 'bar'}), log()]
])
matcher({
foo: 'bar'
})
Rather than duck-typing you could go a step further with this and use instanceof
checks if you really wanted:
const instance = struct => type => type instanceof struct
class Foo {}
const matcher = match([
[instance(Foo), log()]
])
matcher(new Foo())
Exhaustive matching
JS can’t work out if you’ve supplied enough conditions to be exhaustive but match
will accept a lone function to use as a catch-all:
const matcher = match([
['foo', log('::')],
[log('Caught it: ')]
])
matcher('foo')
// ::foo
matcher('bar')
// Caught it: bar
Assignment
Match
will spit out whatever the conditional functions return and so can also be used for assignment:
const matcher = match([
[10, 'the same as']
[v => v < 10, 'lower than'],
[v => v > 10, 'higher than']
])
const return = match(4)
console.log(`4 is ${return} 10`)
// 4 is lower than 10
Running tests
$ npm install
$ npm test
Contributing
Pull requests are always welcome, the project uses the standard code style. Please run npm test
to ensure all tests are passing and add tests for any new features or updates.
For bugs and feature requests, please create an issue.
License
MIT