Scala Tutorials Part #30 - Closures


Closures

This is part 30 of the Scala tutorial series. Check here for the full series.

Index

Introduction

Closure is an important concept in the world of Functional Programming. A considerably simpler definition of a Closure is presented well in this excellent blog post.

A closure is a function that you can pass around that retains the same “environment” as the one it had when it was created.

They are not very unique to Scala, usually they are found in many languages which give emphasis to functions as first class values. To understand closures, let’s understand what object oriented programming offers as a fundamental feature i.e encapsulation of state behaviour.

Encapsulating state and behaviour

Let’s take the below simple class.

class Person {

  //State - Carries data
  var name = "Noname"
  var age = -1

  //Encapsulates behaviour
  def setName (name:String)  {
    this.name = name
  }

  def setAge (age:Int) {
    this.age = age
  }

  def getName () : String = {
    name
  }

  def getAge () : Int = {
    age
  }

}

This is a pretty concise definition of an object. It carries the variables which represent state and the methods which encapsulate behaviour.

In functional programming, instead of passing around objects, we pass around functions. But when we compare objects and functions, we can see that functions in general do not carry state and only carry behaviour.

Free variables

The concept of a free variable comes from mathematics and functional programming theory. They refer to variables which are used locally but enclosed in some scope such as a class of method.

In the below code, the variable interest is defined for the class scope.

 val interestRate = 10

 def printInterest(): Unit = {
   println(interestRate)
 }

The different between a normal function and a closure is that a closure is dependant on one or more free variables. Let’s expand on our above example.

 var increaseRate = 10.0

 calculateIncreasedAmount(1000)

 def calculateIncreasedAmount(amount:Double): Unit = {
   println(s"Increased amount is ${amount * (increaseRate/100)} units")
 }

Here the variable increaseRate is a var and can be changed at any point of the program. In the below example, it changes according to the recent state/value of the increaseRate variable.

var increaseRate = 10.0

calculateIncreasedAmount(1000)

def calculateIncreasedAmount(amount:Double): Unit = {
  println(s"Increased amount is ${amount * (increaseRate/100)} units")
}

increaseRate = 20.0

calculateIncreasedAmount(1000)

At first it prints 100.0 and then 200.0 since the state variable changed.

Reasoning about referential transparency

We saw how functions can be termed pure if they are referentially transparent in part 21. Using the same rules mentioned, is the above function/closure refentially transparent? No, because the variable increaseRate is a var and can be changed anywhere in the flow. If it is a val then it would make the closure referentially transparent and hence pure.

So in order for any closure to be pure, the free variable should be either a val/immutable object. It is good practice to keep the free variable immutable so that the resultant closure is referentially transparent.

In real world Scala usage, you would find that Closures as a language feature is not that extensively used. This is because Scala is a hybrid OO+FP language and developers usually use a combination of Case classes/Case objects along with pure functions. Since Case class are immutable, they still give a good way to deal state while still maintaining things such as referential transparency and not using shared mutable state. Closures are extensively used in pure functional languages such as Haskell, primarily because they are the best way to model state.


Tagged Under


Scala


Search this website...




Keeping up with blogs...

I blog occasionally and mostly write about Software engineering and the likes. If you are interested in keeping up with new blog posts, you should follow me on twitter where I usually tweet when I publish them. You can also use the RSS feed , or even subscribe via email below.

Feedio Subscribe


Share & Like

If you like this post, then you can either share/discuss/vote up on the below sites.



Thoughts ...

Please feel free to share your comments below for discussion

Blog comments powered by Disqus