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 specialise in rapidly transitioning teams to serverless and building production-ready services on AWS.
Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.
Check out my new course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. Including basic concepts, HTTP and event triggers, activities, callbacks, nested workflows, design patterns and best practices.
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