predicate-from

Returns a predicate functions from different kind of values


Keywords
predicate, function
License
MIT
Install
npm install predicate-from@1.0.0

Documentation

Intention

As functional programming becomes more idiomatic in Javascript, it becomes more common to pass conditions as arguments to functions like filter() and likes (dropWhile(), exclude()...) over collections of any sort.

Arrow functions in ES6 provide an efficient syntax for expressing complex predicates, but may not be very redable for complex conditions.

As it is very common to filter collections of objects, predicateFrom provides a very easy and expressive way to express conditions for objects

This module does nearly the same as (discovered afterwards)

I recommand using predicates, as it it focused and full-featured.

Getting started

All examples suppose that predicate-from module is imported as predicateFrom

let pf = require('predicate-from')

Predicates from predicates

If passed a function, predicateFrom will do nothing and return it

This behaviour allows nesting functions in complex objet predicates, where predicateFrom is invoked recursively.

This is very useful for expressing complex predicates with arrow functions or using curried comparison predicates

// considering greaterThan is defined and curried
pf({age: greaterThan(45) }

Predicates from simple values

When passed a primitive value (string, number, boolean of Symbol), predicateFrom will return a predicate which tests with === operator

Mostly used indirectly when building complex predicates

pf('Paris')('London') // false
pf(1)(2) // false
pf(false)(true) // false

Predicates from regular expressions

When passed a RegExp, predicateFrom will return a predicate which simply returns the result of RegExp.test()

Warning:test() returns true for a match anywhere in the tested string. For a full match, be sure to use RegExp special position characters ^ and $

pf(/[0-9]+/)('abcd 1234') // true, partial match at index 5
pf(/^[0-9]+$/)('abcd 1234') // false, start of string is not a digit

Predicates from ranges

When passed 2 numbers or 2 srings, predicateFrom will return a range predicate which tests arg >= a && arg < b

Note: is also works with strings, which can be useful with ISO dates

Mostly used with an explicit invocation of predicateFrom for a property

pf({age:pf(18,35)})({name:'John',age:32}) // true
pf({name:pf('A','D')})({name:'John',age:32}) // false, only accepts names beginning with A, B or C

Predicates from an array of values

Array are used to express an OR condition.

predicateFrom will be invoked on each value of the provided array The resulting function will invoke each predicate on its argument and return true immediately if one of them is satisfied

pf([ 'Paris', 'London'] )('London') // true
pf([ 'Paris', x => x.startsWith('L') ] )('London') // true

Predicates from object literals

When passed an Object literal, predicateFor, each key/value pair will be used to generate a predicate for that specific property. If multiple properties are set, then the resulting predicate will return true only if all the predicate for each properties are satisfied.

For deep properties, just nest objects

let john = { name:'Smith, John'
          ,age:45
          ,job:'carpenter'
          ,address: { city:'Paris', country:'USA', state:'US-TX'} }

pf({job: 'carpenter'})(john) // true
pf({address: { city:'Paris' }})(john) // true
// nested objects are converted to predicates 
pf({job:'carpenter', address: { country:'US' }})(john) // true
// but this will fail
pf({job:'carpenter', address: { country:'FR' }})(john) // false

putting is all together

let inParisUSA = pf({city:'Paris',country:'US'})

// carpenters and plumbers in Paris, USA
pf( { job:['carpenter','plumber], address:inParisUSA})(john) // true
// all Smith in Texas
pf( {name: x => x.startsWith('Smith'), address:{state:'US-TX'}})

Using

It is a very small module (2,3 Kb of source), authored as an ES6 module.

It is available in multiple flavors :

  • lib/main.cjs.js : a CommonJS transpiled to ES5 using Babel
  • lib/main.umd.js : an UMD module transpiled to ES5 using Babel
  • lib/main.es.js : a native ES6 module

The ES6 module flavor is refered by jsnext:main in the package.json. This allows ES6 bundlers like Rollup to use it

Contributing

Rollup is used to compile and generate the different flavors into the lib directory.

All sources are linted with ESLint

The npm scripts are :

  • build : to generate the exported flavors
  • pretest : to compile the tests
  • test : to run the tests using mocha. Tests are run on the CommonJS flavor