Scala Closures with Examples | See What is Behind the Magic


1. Scala Closures

In this chapter, we find out about closures in Scala. We will learn about the problem that Scala Closures solve, Examples of Closures in Scala, see what is behind the magic and working of Datatypes.

Scala Closures

Scala Closures

2. The Problem

What do you do when you want to pass a function around like a variable? How do you let it refer to one or more fields in the same scope? This piece is to address this issue.

3. Scala Closures Introduction and Example

A function whose return value depends on variable(s) declared outside it, is a closure. This is much like that in Python.

We’ve seen how to declare an anonymous function in Scala:

scala> val sum=(a:Int,b:Float)=>a+b
sum: (Int, Float) => Float = $$Lambda$1101/539731466@12ebcdf6

Let’s make a call to it:

scala> sum(2,3)
res2: Float = 5.0

This added the numbers 2 and 3, and returned 5.

Now, consider this version:

scala> var c=7
c: Int = 7
scala> val sum1=(a:Int,b:Int)=>(a+b)*c
sum1: (Int, Int) => Int = $$Lambda$1103/1497170291@4a0a93ce

Here, the function ‘sum1’ refers to the variable/value ‘c’, which isn’t a formal parameter to it. Let’s try calling the function.

scala> sum1(2,3)
res3: Int = 35

So, while ‘sum’ is trivially closed over itself, ‘sum1’ refers to ‘c’ every time we call it, and reads its current value. Let’s try changing the value of c:

scala> c=8
c: Int = 8

We changed ‘c’ from 7 to 8. Let’s try calling sum1 again:

scala> sum1(2,3)
res5: Int = 40

As you can see, it reads the current value of c.

4. Behind the Magic

Coming from a Java or C++ background, this must be nonplussing. Not only did it use the correct value of ‘c’ the first time, it picked up the change in it when we called it a second time. Let’s find out how this works.

In our example, ‘a’ and ‘b’ are formal parameters to the function sum1. ‘c’, however, is a reference to a variable in the enclosing scope. Scala closes over ‘c’ here.

Paul Cantrell, in his article on Closures in Ruby, mentions three criteria for a closure:

  1. We can pass around the code block as a value
  2. At any time, anyone with the value can execute the code block
  3. It can refer to variables from the context we created it in

It is like two lovers separated in distance, yet united by the heart. Not only do they remember each other; they can sense what happens to the other.

5. Another Example

Let’s work up another 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")

I am Ayushi and I am 22

With this example, we hope it gets clearer to you.

6. Working with Other Data Types

Just to be clearer, let’s try this on a data type different that an Integer.

a. Integer Arrays

First, we’ll do this on an Integer array. Let’s declare an array with three numbers:

scala> val nums=Array(1,2,4)
nums: Array[Int] = Array(1, 2, 4)

Next, we define a function to work with this:

scala> val saynum=(a:Int)=>println(s"The number is $a")
saynum: Int => Unit = $$Lambda$1194/2122460177@5b810b54


Now, let’s define a function func:

scala> for(i<-0 to 2){
    | saynum(nums(i))
    | }

The number is 1

The number is 2

The number is 4

b. ArrayBuffer

Now let’s try this with an ArrayBuffer. First, we’ll need to import ArrayBuffer.

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

Now, we declare an ArrayBuffer with three strings:

scala> val colors=ArrayBuffer("Red","Green","Blue")
colors: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(Red, Green, Blue)

Finally, the function func to call sayhello on colors:

scala> val func=(f:String=>Unit,s:String)=>f(s)
func: (String => Unit, String) => Unit = $$Lambda$1270/151863667@5d16f27b

Now, let’s use a for-loop to call this on each value in the ArrayBuffer.

scala> for(i<-0 to 2){
    | func(sayhello,colors(i))
    | }

I am Red and I am 22

I am Green and I am 22

I am Blue and I am 22

This was all on Scala Closures. Hope you like the article on closures in Scala.

7. Conclusion

Does this give Scala a plus over other languages? What do you think? Let us know in the comments.

Leave a comment

Your email address will not be published. Required fields are marked *