matches.js
Matches.js brings the power and expressiveness of pattern matching to Javascript.
Install
npm install matches
var pattern = pattern;var mymap = ; // [2, 4, 6, 8];
Patterns
Literals
Check for specific values using number or string literals, null
, or
undefined
.
var myfn = ;
Wildcards
Underscores will match successfully on any value but ignore it.
var myfn = ;
Identifiers
Patterns that start with lowercase letters will pass the value to the function. Values are passed to the function in the same right to left order they are declared in the pattern.
var myfn = ;
Rest Arguments
Use an ellipsis for rest arguments. A single ellipsis works as a catch all pattern.
var myfn = ;
Arrays
Match on the entire array, or only a few values.
var myfn = ;
Rest Expressions
Rests (...
) can do more than just split up an array. You can combine them
with arbitrary patterns to apply said pattern across every element in the array.
var myfn = ;
Objects
Like with an array, you can match on an entire object, or just a few keys. Unlike arrays, matching is only non-strict. It checks that the keys exist, but other keys are allowed to exist in the object.
var myfn =
Core Javascript Types
Typecheck arguments using Number
, String
, Date
, RegExp
, Function
,
Array
, or Object
.
var myfn = ;
Custom Types
You can add pattern matching support for your own classes.
// Create a new class { thisval = 1;} // Matches.js will check for the non-standard attribute `name` on the constructor// function. If you are in the browser and want wider support, or are using// anonymous functions, make sure you tag your constructor with `className`.MyClassclassName = "MyClass"; // Add the static method `unapply` for array-like matching.MyClass { return objval;}; // Add the static method `unapplyObj` for object-like matching.MyClass { return 'val': objval ;}; // Now you can match on your object.var myfn = ;
Adt.js Types
Adt.js ships with builtin support for matches.js. Adt.js is a library for building algebraic data types or case classes in Javascript.
// Create a new adt.js typevar Tree = adtdata Empty : adt Node : adt; var mytree = Tree
Find out more about adt.js: https://github.com/natefaubion/adt.js
Custom Extractors
Extend matches.js with custom extractors.
// Naive email extractor.// Extractors are passed the value, and a `pass` function. In order to count as// a successful match, the extractor must return an instance of pass.matchesextractors { if typeof val === "string" && val > 0 var parts = val; return ; }; var myfn = ;
Usage
Matches.js exports four functions, pattern
, caseOf
, extract
, and
extractOne
.
var matches = ;var pattern = matchespattern;var caseOf = matchescaseOf;var extract = matchesextract;var extractOne = matchesextractOne;
pattern(patternObj)
The simplest way is to give it an object with the keys being patterns, and the values being functions. Each pattern will be tried in order until a match is found.
var arrayElems = ; ;
pattern(patternStr, successFn)
You can create individual pattern and function pairs.
var emptyArray = ; // "Empty array"; // TypeError: "All patterns exhausted";
pattern(patternFn, successFn)
You can also create your own custom pattern functions. The patternFn
takes
an array of arguments, and should return false
for no match, or a new array
of arguments to forward on to the successFn
.
var { if args0 >= 42 return args0; return false;}; var customPattern = ; // Logs 54; // TypeError: "All patterns exhausted";
caseOf(...args, patternObj)
You can use caseOf
to do ad-hoc pattern matching on objects. It's the same
as immediately invoking a pattern
function, but lets you put the arguments
first.
var result = ; // Is the same as...var result = 42;
extract(patternStr, ...args)
Use extract to pull values out of other values. It works much like match
on
strings. If there was a succesful match, it will return an array of extracted
values. If the match failed, it will return null
.
var res = ;
extractOne(patternStr, ...args)
This is like extract
but returns the first value instead of an array. This
works well for traversing a deep structure.
var val = ;
Note: this will also return undefined
on failure. So keep that in mind if
undefined
could be a valid value.
Combinators
You can combine any of these methods to create unique match chains using the
alt
combinator.
var wildcard = ;var mychain = alt { return "Two"; } { return "Three"; } altwildcard; // 'One'; // 'Two'; // 'No matches.';
Multiple Arguments
Separate matches for multiple arguments with a comma. Since you can pass any number of arguments to functions in Javascript, Matches.js is not strict and will happily combine patterns for varying numbers of arguments. However, Matches.js is strict on the number of arguments within the pattern.
var myfn = ;
Performance
Pattern strings are compiled to pure Javascript functions and then cached, so in general, they are quite fast.
On a 2GHz core, average compilation time is around .12ms for a pattern comprised of 5-6 sub-patterns. Pattern matched functions are around 3-4x slower to dispatch than an equivalent hand-optimized function that does similar type-checking. Keep in mind, that time is measured in the single microseconds (1µs vs 3µs) to dispatch 5 calls to the same function.