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