npm package: @kircher.tech/matchem
Description: Simple chained pattern-matching-like conditional library for JS
Author: Nicholas Kircher
Latest version: 0.1.0

# Match'em!

Sorry, that was the only name with "match" I could find that wasn't already taken.

So this is yet another pattern-matching-esque library for JS.  I just wanted a super simple API, with the ability to pass either values or functions as predicates and transformers.  So, this is basically that.

## Installation

- In a terminal: `yarn add @kircher.tech/matchem` or `npm install --save @kircher.tech/matchem`
- Somewhere in yer project: `import matchWhen from '@kircher.tech/matchem';`
- Party!

## Usage

An example here:

```javascript
const runMatcher = (
  matchWhen((x) => x > 100, (x) => x + ' is greater than 100!')
    .orWhen((x) => x > 50, 'Greater than 50')
    .orWhen((x) => x >= 25, 'Greater than 25')
    .otherwise('Less than 25')
);

runMatcher(27); // => "Greater than 25"
```

If more than one predicate evaluates to true, only the first one matched will be used.  For example:

```javascript
const runMatcher = (
  matchWhen(true, 'This will be the return value')
    .orWhen(true, 'This will not')
    .otherwise('And neither will this')
);

runMatcher(); // => "This will be the return value"
```

A call to `matchWhen` returns an object with the two methods `orWhen` and `otherwise`.  A call to `otherwise` returns a function that takes one or many values, tests each predicate against the values until it finds a truthy result, then returns the result of calling the matching transformer function for that predicate on the values.  If one is not found, the transformer given to `otherwise` will be called (or will be returned if it's not a function).

Effectively, calls to `matchWhen` and `orWhen` create conditional pairs that are accumulated.  `otherwise` signifies what to do in the event that none of those conditional pairs have a predicate that evaluates to true.  A call to `otherwise` must be the last call in the chain.

Both `matchWhen` and `orWhen` expect 2 arguments, which can both be either functions or values:

- a predicate, tested against a given value
- a transformation, used to either transform the given value, or replace it

For `otherwise`, only the `transformation` argument is needed.

For example, here's what you'd get back from a call to `orWhen` without the `otherwise`:

```javascript
const foo = (
  matchWhen((x) => x > 5, (x) => x + 100)
    .orWhen(true, 'This is some test data?!')
); // => { orWhen: [Function], otherwise: [Function] }
```

The signature of matchWhen is somewhat like this:

```haskell
type MatchPredicateFn p t = p -> t -> { orWhen :: MatchPredicateFn, otherwise :: (t -> (v -> t)) }

matchWhen :: MatchPredicateFn
```

Except each call to orWhen can have different types for p and for t, and does not need to match the types from the initial matchWhen fn.

## More Examples

As an if statement replacement when formatting a price:

```javascript
const formatPrice = (
  matchWhen(equals(0), 'Free')
    .orWhen(value => value > 100000, 'Call us for a price')
    .otherwise(formatCurrency('dollars'))
);

formatPrice(0); // => "Free"
formatPrice(150000); // => "Call us for a price"
formatPrice(5600); // => $56.00
```