De Morgan's Laws

De Morgan's laws are a pair of boolean algebra rules, if written in javascript-style boolean expressions, they look like this:

!(A && B) is equivalent to !A || !B
!(A || B) is equivalent to !A && !B


This is not only useful for boolean simplification, but also for general problem solving. For example, in underscore.js there is a function called .every that returns true if every value in a collection passes a truth test. There is also a function called .some that returns true if any value in the collection passes the truth test. Normally, the logic of _.some can be written similar to this:

var _.some = function(collection, test) {
  var anyPass = false;

  for (var i = 0; i < collection.length; i++) {
    anyPass = anyPass || (test(collection[i]));
  }

  return anyPass;
};

This straightforward implementation can be simplified slightly with .reduce. However, there is also a clever way to reimplement the same function with .every. Can you think of a way? (Hint: It has to do with the title of this blog post.)


The trick depends on the overlap between the two functions. The relationship may not be apparent at first, but using De Morgan's laws, it can be shown rather easily:

    A || B || C
->  !!(A || B || C)
->  !(!A && !B && !C)

Using a double negation, we yield a logical equivalency between two boolean expressions that can be summarized as this:

Some elements pass the truth test is equivalent to Not all elements fail the truth test.

With this knowledge in hand, we can reimplement _.some with some cleverness, as shown here:

var _.some = function(collection, test) {
  return !_.every(collection, function(element) {
    return !test(element);
  });
};
Written on September 25, 2015