@mattstyles/match

1.0.1 • Public • Published

match

Pattern matching algorithm

Build Status npm version Dependency Status js-standard-style

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

Readme

Keywords

none

Package Sidebar

Install

npm i @mattstyles/match

Weekly Downloads

1

Version

1.0.1

License

MIT

Last publish

Collaborators

  • mattstyles