Complement and partial in javascript

I started learning Clojure last week using the online book "Clojure for the brave and true". (If you are doing the same and having trouble with getting the REPL working in Emacs then see this post on the Google group.)

Clojure is the first functional programming language that I have learnt. While I have found it fun so far I haven't yet had an "aha" moment about functional programming. When the author is excited about something, I quite often think, "Well, you could do that in Ruby." I'm not a Ruby fanboy, it's just that Ruby is the language that has come to mind most while I learn Clojure.

I've just read about the Clojure functions complement and partial. These felt like the first things that were really new to me. I decided to implement these in a language that I had more experience of in order to "pinch" myself. I think I have acclimatised so quickly to Clojure that I'm in danger of taking any awesomeness for granted.

I've written my implementations of complement and partial in javascript. It just seemed like a good idea at the time. I used the Rhino runtime as a kind of syntax checker before running my samples in a browser. The version of Rhino on my distro does not seem to recognise the javascript spread syntax, so I have not used that.

Complement

The complement function is pretty easy to implment. All that is required is to create a function that will call the supplied function and then apply a boolean not to the result. Here's my version:

function complement(fn) {
    return function() {
        return !fn.apply(null, arguments)
    }
}

We can use the complement function very simply, although I quickly realised that we can't always use it as simply as in Clojure. In Clojure, operators like > and + are conventional functions and can be passed as an argument just like any other function. Not so in javascript. I have defined a very simple function to take the place of the > operator.

function greater(a,b) {return a>b}

And can use it with complement to create a new function like this:

// less-than-or-equal
var lte = complement(greater);

Here is the created function in use:

>> lte(4,3)
← false
>> lte(4,4)
← true
>> lte(4,5)
← true

Partial

The partial function is only a little more complex than complement. We need to create a function that will call the supplied function with the arguments supplied when the partial function is created and the arguments supplied when the partial function is called:

function partial(fn) {
    // Collect all the arguments other than "fn"
      var partial_args = [].slice.call(arguments, 1)

      return function() {
        var all_args = partial_args.concat([].slice.call(arguments))
        return fn.apply(null, all_args)
      }
}

And this is how partial is used:

// less-than-3
var lt3 = partial(greater, 3);

>> lt3(2)
← true
>> lt3(3)
← false
>> lt3(4)
← false

And, of course, we can combine partial and complement easily because they both accept and return functions:

// greater-than-or-equal-to-3
var gte3 = complement(partial(greater,3));

>> gte3(2)
← false
>> gte3(3)
← true
>> gte3(4)
← true

Justin Hellings

"Justin? Hell of a guy! We would have kept him but you know how it is. Genius like that is always restless ... Eh? ... Oh, him ... No, I thought you meant someone else."



comments powered by Disqus