Skip to content

Predicates

marcellosachs edited this page Jul 28, 2016 · 2 revisions

Immutable uses predicate functions for a few methods including filter, every, and count. Predicates are also used in many JavaScript Array methods.

Predicates have the signature: <K, V>(value?: V, key?: K, iter?: Iterable<K, V>) => boolean

Predicates must be pure, always returning the same value based on the given inputs.

Complement (Not)

How nice of you. Many methods on Immutable collections which accept a predicate have equivalents expecting a predicate which returns the opposite. For example, every and some, filter and filterNot, skipWhile and skipUntil. If you come across a case where using different methods is burdensome but you need the ability to create a complement of a predicate, this builder is useful:

function not(predicate) {
  return function() {
    return !predicate.apply(this, arguments);
  }
}

Another way to express filterNot:

var data = Immutable.fromJS([ 1, 2, 3, 4, 5 ]);
data.filter(not(x => x % 2 === 0));
// List [ 1, 3, 5 ]

Pick & Omit

A common usage of filter is to "pick" a number of keys from a Collection, popularized by underscore and lodash. A helpful predicate builder to have filter behave like pick:

function keyIn(/*...keys*/) {
  var keySet = Immutable.Set(arguments); 
  return function (v, k) {
    return keySet.has(k);
  }
}

If you're using ES6, using arguments in this way won't work. Instead, use the spread operator :

function keyIn(...keys) {
  var keySet = Immutable.Set(keys); 
  return function (v, k) {
    return keySet.has(k);
  }
}

Then pick and omit looks like:

var data = Immutable.Map({ a: 1, b: 2, c: 3, d: 4 });
data.filter(keyIn('a', 'c')); // pick
// Map { a: 1, c: 3 }
data.filterNot(keyIn('a', 'c')); // omit
// Map { b: 2, d: 4 }