Scala – Closures | Why closure? What are the benefits of a Closure?

If You are interested to learn about the Scala Basic Functions

closure is a function, whose return value depends on the value of one or more variables declared outside this function.

The following piece of code with anonymous function.

val multiplier = (i:Int) => i * 10

Here the only variable used in the function body, i * 10 , is i, which is defined as a parameter to the function. Try the following code −

val multiplier = (i:Int) => i * factor

There are two free variables in multiplier: i and factor. One of them, i, is a formal parameter to the function. Hence, it is bound to a new value each time multiplier is called. However, factor is not a formal parameter, then what is this? Let us add one more line of code.

var factor = 3
val multiplier = (i:Int) => i * factor

Now factor has a reference to a variable outside the function but in the enclosing scope. The function references factor and reads its current value each time. If a function has no external references, then it is trivially closed over itself. No external context is required.

Try the following example program.

Example

object Demo {
   def main(args: Array[String]) {
      println( "multiplier(1) value = " +  multiplier(1) )
      println( "multiplier(2) value = " +  multiplier(2) )
   }
   var factor = 3
   val multiplier = (i:Int) => i * factor
}

Save the above program in Demo.scala. The following commands are used to compile and execute this program.

Command

\>scalac Demo.scala
\>scala Demo

Output

multiplier(1) value = 3
multiplier(2) value = 6

Example of Scala Closures

Let’s work up another Scala Closures example.

scala> var age=22
age: Int = 22
scala> val sayhello=(name:String)=>println(s"I am $name and I am $age")
sayhello: String => Unit = $$Lambda$1065/467925240@78b9155e
scala> sayhello("Ayushi")

I am Ayushi and I am 22
Now, let’s take another function func that takes two arguments: a function and a string, and calls that function on that string. Did we mention that Scala supports higher-order functions?

scala> def func(f:String=>Unit,s:String){
    | f(s)
    | }
func: (f: String => Unit, s: String)Unit
scala> func(sayhello,"Ayushi")

What if the closure modifies the value of a free variable?

If a closure modifies the free variable, the changes are visible outside the closure.

var p = 10
def getHike(salary: Double) = {
p = p * 2
salary * p / 100
}
println(p)
//10
getHike(5000)
//res8: Double = 1000.0
println(p)
//20

Why closure? What are the benefits of a Closure?

We learned that in functional programming, you could pass functions and return functions. Don’t you think that it is similar to OOP?
In the OOP approach, we pass objects around, and in Functional Programming, we juggle with functions. Both are the same kind of things. Isn’t it? If you agree with this, You can easily argue that objects are more flexible than functions.
Why?
For certain use cases, Objects are more flexible because objects carry two things. They carry methods as well as the data elements. Whereas, a function is alone because It does not have any state or a data item. So, if we have a requirement, where we need to pass a bunch of states along with a function, how will you do it?
The answer to this problem is a Closure and the free variables. Let’s look at an example to see it in action.
We looked at the getHike function. Let me give you a realistic requirement. I have a list of employee numbers. It is something like shown below.

val l = (1001 to 1005).toList
l.map(getHike)

I want a function that I can apply to all of these ids and get the hike for all of them. It should work like the second line of code shown above. Here is the code for the getHike function.

def getHike = {
//Load employee and their current salary
val e: Map[Int, Double] = Map(
1001 -> 35000.00,
1002 -> 43000.00,
1003 -> 28000.00,
1004 -> 54000.00,
1005 -> 17000.00
)
// Some logic to derive percentage for each employee
val p: Map[Int, Double] =
Map(1001 -> 10.00, 1002 -> 12.00, 1003 -> 7.50, 1004 -> 6.80, 1005 -> 20.00)
(empID: Int) => (empID, e(empID) * p(empID) / 100.00)
}

There are many things in the code, but I want you to focus on the last line. The last line is an anonymous function body. The getHike is a Higher Order function because it returns another function. The below code demonstrates the main idea.

val f = getHike
f: Int => (Int, Double) = <function1>
//Get Hike for an employee
f(1001)
//res10: (Int, Double) = (1001,3500.0)
//Get Hike for a non existant employee
f(1006)
//java.util.NoSuchElementException: key not found: 1006

The first line makes a call to getHike that returns a function. The returned function takes an integer and gives a tuple of an integer and double.
In the next line, we call the function f with an employee number. It will give you the hike.
Further, In the next line, we pass an employee number that doesn’t exist and get an exception. Now, I have a question.
Where is the f looking for employee number?
Look at the code for getHike. We have e and p> defined there. They are local values for the getHike function. But they are free variables for the anonymous function body in the last line.
Now, here is the point that I want to make.
The anonymous function returned from the last line is a closure. It uses two free variables, e> and p>. When we return it from the getHike, it carries the state of the e> and the p> with it. So, f contains the data with it. Isn’t it?.
It is just like an object in the object-oriented world. When you start practicing Functional Programming, you will realize that closures and their capability to carry the state is incredible. It saves you a lot of complicated and unnecessary code and simplifies your solution.

Scala – Closures | Why closure? What are the benefits of a Closure?
Show Buttons
Hide Buttons