Scala Tutorials Part #30 - Closures
Originally Posted On : 29 Jun 2018
Closures
This is part 30 of the Scala tutorial series. Check here for the full series.
Index
- Introduction
- Encapsulating state and behaviour
- Free variables
- Reasoning about referential transparency
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.
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.
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.
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.
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.