cmpr

0.0.17 • Public • Published

cmpr

cmpr is an comparison and validation library with pattern matching that is written to be easily composable - thus extendable to suit any need.

Getting started

One thing to note is that all functions in cmpr are curried. If you haven't heard about currying before, don't worry. All you need to know to use cmpr is that:

eq(1, 1) // true

...becomes...

eq(1)(1) // true

This makes it easier to compose comparisons and validators for your own use:

import { isInstanceOf, pipeTests, isArrayOf } from 'cmpr';
 
function Movie(title, rating) {
  this.title = title;
  this.rating = rating;
}
 
const movies = [
  new Movie('Sound of Music', 8.0),
  new Movie('Angry Men', 8.9),
];
 
const isMovie = isInstanceOf(Movie);
const isGoodMovie = a => a.rating >= 7.5;
const goodMovieTest = pipeTests(isMovie, isGoodMovie);
const hasGoodMovieTaste = isArrayOf(goodMovieTest);
 
hasGoodMovieTaste(movies); // true

Shallow and deep comparison

Shallowly comparing an array or object is very straight forward:

import { isShallowEq } from 'cmpr';
 
isShallowEq(['Hiromi', 'Chick', 'Jordan'])(['Hiromi', 'Chick', 'Jordan']); // true
               |                                |
               |- Has primitive value equality -|
 
isShallowEq([ { name: 'Hiromi Uehara' } ])([ { name: 'Hiromi Uehara' } ]); // false 
                         |                                |
                         |---- No referential equality ---|

A shallow compare will compare the values in an array or object by value for primitives and reference for objects.

A deep compare does the same thing but will recurs on objects so it can compare the primitives held inside.

import { isDeepEq } from 'cmpr';
 
isDeepEq({
  artists: [
    { name: 'Pat Metheny',
      featuredAlbum: 'Secret Story' },
  ]
})({
  artists: [
    { name: 'Pat Metheny',
      featuredAlbum: 'Secret Story' },
  ]
}); // true

Fuzzy comparisons

Shallow and deep compares have fuzzy versions. This allows us to define subsets to match for in our comparisons.

import { isShallowFuzzyEq } from 'cmpr';
 
isShallowFuzzyEq(['Brain'])(['Move', 'Brain', 'Spiral']); // true
 
isShallowFuzzyEq({
  drums: 'Morgan Ågren'
})({
  drums: 'Morgan Ågren',
  keyboard: 'Mats Öberg',
}); // true
import { isDeepFuzzyEq } from 'cmpr';
 
const hasMove = isDeepFuzzyEq({
  'Hiromi Uehara': { Move: { year: 2012 } },
});
 
const albums = {
  'Pat Metheny': {
    'Secret Story': {
      year: 1992,
    },
  },
  'Hiromi Uehara': {
    Move: {
      year: 2012,
    },
  },
};
 
hasMove(albums); // true

Comparators (pattern matching)

cmpr can create comparators that describe how values should be compared. We can nest these descriptive objects in our comparisons to achieve pattern matching.

const theTrioProject = {
  piano: new Pianist('Hiromi Uehara'),
  drums: new Drummer('Simon Phillips'),
  bass: new Bassist('Anthony Jacksson'),
};
 
const isValidLineup = isShallowEq({
  piano: isInstanceOf__(Pianist),
  drums: isInstanceOf__(Drummer),
  bass: isInstanceOf__(Bassist),
});
 
isValidLineup(theTrioProject); // true

...which can be rewritten to be more composable...

const hasPianist = isShallowFuzzyEq({ piano: isInstanceOf__(Pianist) });
const hasDrummer = isShallowFuzzyEq({ drums: isInstanceOf__(Drummer) });
const hasBassist = isShallowFuzzyEq({ bass: isInstanceOf__(Bassist) });
 
const isValidLineup = pipeTests(hasPianist, hasDrummer, hasBassist);
 
isValidLineup(theTrioProject); // true
const myArr = [1, 2]
 
isShallowEq([1, myArr, isBool_])([1, myArr, true]); // true
             |    |       |
             |    | by reference
             |            |
             | by value   | by comporator
 
isDeepEq([1, [1, 2], isBool_])([1, [1, 2], true]); // true
          |    |        |
          |    | recursive isDeepEq
          |             |
          | by value    | by comporator

Wildcard comparator

cmpr provides a special wildcard comparator that can be used to fill in blanks in your matching, for example:

import { _ } from 'cmpr';
// alias: import { wildcard_ } from 'cmpr';
 
isShallowEq(_)(x); // true
isShallowEq([_])([x]); // true
isShallowEq({ a: _ })({ a: x }); // true
isShallowEq([x, _, x])([x, z, x]); // true
isShallowEq({ a: _, c: x })({ a: z, c: x }); // true
 
isShallowEq([x, _, x])([x, z, z]); // false
isShallowEq([_, x])([x]); // false
isShallowEq({ a: _, c: x })({ c: x }); // false

Examples

Example uses of cmpr:

  • eav - Experimental spy library leveraging Proxy API that uses cmpr for matching called arguments.
  • ptrn - Use cmpr to declare functions with pattern matching.

API

Visit the Wiki to read the auto-generated API documentation.

Package Sidebar

Install

npm i cmpr

Weekly Downloads

1

Version

0.0.17

License

MIT

Last publish

Collaborators

  • functorism