In F#, you can’t overload a let-bound function, and whilst it’s a hindrance sometimes you can generally work around it easily enough since you can still overload members of a class. All you need to do is to wrap the module and constituent functions into a class and overload the class members instead.
This is where multi-arity functions come in in Clojure (an arity is simply the number of arguments that a function can take).
One way to define multi-arity functions is to use the defn macro, for instance:
As you’ve probably noticed, it’s possible for one overload to call another, so you can use this technique to set default argument values as shown above. On its own, that’s not very interesting, and an effect that can be easily replicated in F# using a combination of optional parameters and the built-in defaultArg function with class members, even without resorting to overloading (again, this is sadly only supported with class members and not functions..).
What is definitely more interesting is Clojure’s support for variadic functions – functions with infinite arity.
A variadic function has a & symbol in its arguments list, which tells the compiler that the next parameter collects all remaining arguments as a sequence. So, if we rewrite the greet function to take one or more arguments we can end up with a variadic function such as:
As you can see, the arguments “Darryl”, “Deepu” and “Tom” has been packed into the argument rest in the function definition and printed as a list (Clojure’s lists are enclosed in parentheses ( ) just like its function invocations). If you come from a .Net background then this behaviour should be familiar to you, because that is how parameter arrays works in .Net.
So what’s so special about variadic functions in Clojure then?
To quote Sebastian Shaw from the excellent X-Men First Class film:
In Clojure, there’s a built-in apply function which allows you to ‘unpack’ a sequence and pass the unpacked values to a function as individual arguments. With this, we can now rewrite the variadic version of greet as follows:
Notice that the arguments “Darryl”, “Deepu” and “Tom” are no longer treated as a list but as individual arguments to the print function, pretty neat. This SO answer also sheds some more light on why variadic functions exist in Clojure with some interesting examples and idiomatic use of this type of functions.
I’m an AWS Serverless Hero and the author of Production-Ready Serverless. I have run production workload at scale in AWS for nearly 10 years and I have been an architect or principal engineer with a variety of industries ranging from banking, e-commerce, sports streaming to mobile gaming. I currently work as an independent consultant focused on AWS and serverless.
Here is a complete list of all my posts on serverless and AWS Lambda. In the meantime, here are a few of my most popular blog posts.
- Lambda optimization tip – enable HTTP keep-alive
- You are thinking about serverless costs all wrong
- Many faced threats to Serverless security
- We can do better than percentile latencies
- I’m afraid you’re thinking about AWS Lambda cold starts all wrong
- Yubl’s road to Serverless
- AWS Lambda – should you have few monolithic functions or many single-purposed functions?
- AWS Lambda – compare coldstart time with different languages, memory and code sizes
- Guys, we’re doing pagination wrong