Negating Predicate Functions in JavaScript

While you may not have heard the term, chances are you've used predicate functions before. A predicate is essentially a function that determines whether something is true or false based on its arguments. It is common (though not necessary) for predicates to be named "isX", such as isEven or isNumber.

Suppose that we have a program which deals with cataloging comic book heroes and villains represented as simple objects:

varsuperman={name:"Superman",strength:"Super",heroism:true};

And as part of that program we have a number of predicates that might look something like this:

As you can see, this is a bit repetitive. But the problem isn't that the code is longer. Rather, the problem is that for each pair of predicates (the "is" and "isNot") we are defining our core logic twice. Having that logic repeated means we are more likely to make mistakes like updating only one of the predicates when our logic changes.

What can we do to fix that problem? Our first thought might be to do something like this:

While this is certainly an improvement, we still have repetition of a different kind. Both of our "isNot" predicates share a piece of core logic. They both reverse the sense of the predicates that they are based upon.

Wouldn't it be nice if we could abstract that away into something clearer and more maintainable? Fortunately, we can.

This is another example of treating functions as first-class values in JavaScript. The negate function accepts a predicate as an argument, and returns a function whose sense is the opposite of the original predicate.

Everything continues to work as expected. But now we've pulled the shared logic of the "isNot" predicates into one location. And it is much easier to tell at a glance that the definitions of the "isNot" predicates are derived from the "is" predicates.

Applied to only a couple of functions, this refactoring may not look like much. But applied to dozens of functions scattered throughout a complex system, negate can help to make things much more maintainable.