Hello! Today, let’s explore the domain of functional programming with partially applied functions and currying.
It's fairly common for developers to confuse partially applied functions and currying since both concepts involve manipulating functions and arguments in functional programming. Let’s clarify these concepts.
All the examples in this issue will be based on the following function that sums three integers1:
def add(x: Int, y: Int, z: Int): Int = x + y + z
Partially Applied Function
A partially applied function is a function created by fixing some of the arguments of a function, resulting in a new function that requires fewer arguments.
Imagine that we frequently need to calculate the result of 5 + y + z
. Instead of calling add
with x = 5
each time, we can create a partially applied function by fixing the first argument:
val addFive = add(5, _: Int, _: Int)
NOTE: The underscores (
_
) are placeholders for arguments that will be provided later.
This example creates a partially applied function, addFive
, that takes only two arguments instead of three. We can call it this way:
val result = addFive(2, 3)
Partially applied functions help simplify complex functions by pre-fixing some arguments, creating more specialized and potentially more reusable functions.
Currying
Currying is the process of transforming a function that takes multiple arguments into a series of functions, each taking a single argument.
Here’s a curried version of the add
function:
def curriedAdd(x: Int)(y: Int)(z: Int): Int = x + y + z
To call this function, we pass arguments one at a time:
val result = curriedAdd(1)(2)(3) // 6
This example produces the same result as add(1, 2, 3)
but allows the function to be called as a series of single-argument calls.
Are you still wondering about the benefits of currying? That’s understandable. Currying on its own might not seem particularly useful. However, it becomes powerful when combined with partial application.
Let’s revisit our goal of fixing x
to 5. Without currying, we used this syntax:
val addFive = add(5, _: Int, _: Int)
With currying, the syntax becomes clearer:
val addFive = curriedAdd(5)
Instead of the cumbersome syntax with placeholders, this approach provides a more concise and readable way to create a partially applied function.
Conclusion
While partially applied functions and currying are closely related, they serve distinct purposes:
Partially applied functions fix some arguments of a function, simplifying it for reuse.
Currying transforms a function into a chain of single-argument functions.
Partially applied functions combined with currying enable a cleaner and more concise syntax to break down complex functions into smaller, reusable components.
Explore Further
Have you used currying or partially applied functions in your projects? Please share your thoughts in the comments.
The examples are in Scala, but even if you’re not familiar with the language, the code snippets should be fairly intuitive to grasp.