Scala - Currying Functions
This chapter takes you through the concept of currying functions in Scala programming. Currying is a technique that transforms a function with multiple arguments into a sequence of functions that each with a single argument.
Currying Functions
You can decompose a function that takes multiple parameters into a series of functions that each take a single parameter. It is used to create more modular and reusable code.
Currying is the process of transforming a function that takes multiple arguments into a chain of functions each taking a single argument.
Syntax
The syntax of a curried function in Scala is -
def functionName(arg1: Type1)(arg2: Type2)(arg3: Type3): ReturnType = {
// function body
}
Example
The following example shows defining and using a curried function in Scala programming -
object Demo {
def add(a: Int)(b: Int): Int = {
a + b
}
def main(args: Array[String]): Unit = {
println(add(3)(4)) // Output: 7
val addThree = add(3) _
println(addThree(4)) // Output: 7
}
}
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
7 7
In the example, the add function is curried. So it has to be called with one argument at a time.
Advantages of Currying Functions
There are various advantages of Currying functions. You can fix a few arguments of a function and produce a new function with less number of arguments. It is easier to build complex functions from simpler ones. You can also work with higher-order functions. So it enhances code modularity and reusability.
Partial Application with Currying
You can also use currying functions through partial application. You partially apply a function by fixing some of its arguments and returning a new function.
Syntax
The syntax for partially applying a curried function is -
def functionName(param1: Type1)(param2: Type2): ReturnType = {
// function body
}
val partiallyAppliedFunction = functionName(fixedParam1) _
Example
Consider the example of partial application with curried functions in Scala programming -
object Demo {
def multiply(a: Int)(b: Int): Int = {
a * b
}
def main(args: Array[String]): Unit = {
val multiplyByTwo = multiply(2) _
println(multiplyByTwo(5))
println(multiplyByTwo(10))
}
}
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
10 20
In the example, the multiply function is curried. It is partially applied to create a new function multiplyByTwo.
Currying and Function Composition
You can compose functions to pass partially applied functions as arguments to other functions.
Syntax
The syntax for composing functions with currying is -
def function1(param1: Type1)(param2: Type2): ReturnType1 = {
// function1 body
}
def function2(param: Type3): ReturnType2 = {
// function2 body
}
val composedFunction = function2 _ compose function1(fixedParam1)
Example
Consider the example of function composition with curried functions in Scala programming -
object Demo {
def add(a: Int)(b: Int): Int = a + b
def double(x: Int): Int = x * 2
def main(args: Array[String]): Unit = {
val addThree = add(3) _
val addThreeAndDouble = double _ compose addThree
println(addThreeAndDouble(4))
}
}
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
14
In the example, the add function is curried. It is composed with the double function to create a new function addThreeAndDouble.
Currying and Higher-Order Functions
You can use Currying combined with higher-order functions. So you can create highly modular and reusable code.
Syntax
The syntax for using curried functions with higher-order functions is -
def higherOrderFunction(f: Type1 => Type2): ReturnType = {
// function body calling f
}
def curriedFunction(param1: Type1)(param2: Type2): ReturnType = {
// function body
}
Example
Consider the example of using curried functions with higher-order functions in Scala programming -
object Demo {
def applyFunction(f: Int => Int, x: Int): Int = {
f(x)
}
def add(a: Int)(b: Int): Int = a + b
def main(args: Array[String]): Unit = {
val addFive = add(5) _
println(applyFunction(addFive, 10))
}
}
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
15
In the example, the add function is curried. It passed as an argument to the higher-order function applyFunction.
Currying and Recursion
You can apply Currying in recursive functions to create elegant and concise solutions to complex problems.
Syntax
The syntax for recursive curried functions is -
def recursiveFunction(param1: Type1)(param2: Type2): ReturnType = {
// base case
if (condition) baseResult
else {
// recursive case
recursiveFunction(newParam1)(newParam2)
}
}
Example
Consider the example of recursive curried functions in Scala programming -
object Demo {
def gcd(a: Int)(b: Int): Int = {
if (b == 0) a
else gcd(b)(a % b)
}
def main(args: Array[String]): Unit = {
println(gcd(54)(24))
}
}
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
6
In the example, the gcd function is a recursive curried function. It computes the greatest common divisor of two numbers.
Currying Recursion Summary
- Currying transforms a function with multiple arguments into a sequence of functions that each with a single argument.
- You can use Currying in partial application, function composition, and with higher-order functions. So, it is easier to create new functions by fixing some arguments of existing functions.
- The syntax for declaring curried functions can be different but the core concept remains the same.
- It enhances code modularity and reusability because functions are broken down into simpler and more manageable parts.
- It can be used in recursion and combined with other functions to solve complex problems elegantly.