Monday, May 25, 2015

Living with Variadic Functions in Clojure and JavaScript

"No wonder, my lord – one lion may, when many asses do."
-- Shakespeare, A Midsummer Night's Dream
Act V, Scene I, Line 152

Splat


Often in programming (and life) you do not get exactly what you want.  Say we have a simple function which adds numbers together.  How should the input be structure?  Should we require the caller to place all the values into some type of collection?  Why can't the caller pass in the values one at a time into the function?

Splatting in JavaScript allows a function to accept a variable number of arguments, this is called a variadic function.  A variadic function allows for a variable arity, which is a fancy term for what is often called arguments.

Say we want the following:


We would like to be able to call our summer function with a variable number of arguments but we want to be able to work with the arguments like they were in a collection.  This is were splatting comes into play.



In the plain old JavaScript example we see the following:

Array.prototype.slice.call(arguments, summer.length)

This is how to do a splat in plain old JavaScript.  We are taking the argument object then we slice off the number of arguments which the function normally takes using Function.lenght, in the case of summer the Function.length value is 0.  By doing all of this we now have an array with all of the arguments passed into the summer function.  We can now call Lodash's reduce with the arguments to obtain the sum.

In the ES6 example we see we can use the new splat operation ... (also called spread) to get an array of the arguments passed in.  This is a lot easier than using the slice, arguments, and Function.length pattern that we see in the plain old JavaScript code.

Apply


How would we do something like this in Clojure?



We see in Clojure we can destruct the parameters using the & to obtain the rest of the parameters, in the case of summer & values will give us everything the function is called with.  We can then apply this collection against the + function using apply.  Apply allows use to pass in a collection as the last argument to a function which does not take collections.

In Clojure we do not need a summer function since that is exactly how the + function works.