FunHop: Understanding Referential Transparency

In this episode of FunHop, we would try to look at what is Referential Transparency, what is substitution model and how being immutable really helps.

Referential transparency means that we can exchange the expression by its value or a value by the expression and nothing changes. Pure functions are referentially transparent. Any function f(a)=b is a pure function if for the same “a” we end up getting the same “b” without any internal or external state change.

For example the + function is a pure function
2 + 3 and

val c= 2
c + 3

would always yield the same result. There are no side effects either.

Now, let us look at Referential Transparency.

Loot at the code block below

```val x = 7
val c = x + 2
val d = c + 3```

Now, the value of c remains 9 even if we substitue the expression with the value of x which is 7. Taking it a step further, lets look at the following code

```val x=7
val c= 7 + 2, and
val d = 7 + 2 + 3```

As you would agree, the results would remain the same.
Hence, if the expression can be replaced by its value and vice versa AND nothing changes then it is called Referential Transparency. This model of substituting values for expressions is called Substitution Model.

Substitution model gives us a way to naturally reason code. You would observe that substitution model lends itself easily to immutability. Only when objects are immutable, we can substitute them without any concerns on the results. Ok, let us look at a more concrete example

For example, let us refer to a money class which is represented like this

```case class Money(var amt: Int) {
def add(anotherAmt: Int): Money = {
this.amt += anotherAmt
this
}```

Aha! some weirdness here, the add method mutates the money object and returns the mutated object. Now, for the following block of code

```object RefTrans extends App {
val money1 = new Money(10)

}```

The output is

Now going by the Referential Transparency and Substitution model, let us replace money2 by the expression for money2 which is money1.add(20)
Hence our code becomes

```object RefTrans extends App {
val money1 = new Money(10)

}```

Now the output becomes

Weird Huh? 😉

This is different than what we got first. This shows that money2 expression is NOT referentially transparent. We cannot substitute the expression with its values and get the same result.

Ok, now let us change the code a little and have GoodMoney instead which DOES NOT mutate the object.

```case class GoodMoney(val amt: Int) {
def add(anotherAmt: Int): GoodMoney = GoodMoney(this.amt + anotherAmt)
}```

Now let us start the same cycle with GoodMoney

```object RefTrans extends App {
val money1 = new GoodMoney(10)

}```

The output is

And now let us do the substitution,

```object RefTrans extends App {
val money1 = new GoodMoney(10)

}```

What do you expect the output to be?
Of course it is the same

Hence, as you would observe that substitution when it is referentially transparent, saves us the headache of mapping state transitions, which is not easy. Immutability lends itself directly to referential transparency and substitution model. The evaluated expression when doing substitution is purely local and requires only local reasoning. If the operations on your object return another object and are immutable then you are good.

The code is present on the Knoldus GitHub Account. Till we meet again, write immutable code.

Written by Vikas Hazrati

Vikas is the CEO and Co-Founder of Knoldus Inc. Knoldus does niche Reactive and Big Data product development on Scala, Spark, and Functional Java. Knoldus has a strong focus on software craftsmanship which ensures high-quality software development. It partners with the best in the industry like Lightbend (Scala Ecosystem), Databricks (Spark Ecosystem), Confluent (Kafka) and Datastax (Cassandra). Vikas has been working in the cutting edge tech industry for 20+ years. He was an ardent fan of Java with multiple high load enterprise systems to boast of till he met Scala. His current passions include utilizing the power of Scala, Akka and Play to make Reactive and Big Data systems for niche startups and enterprises who would like to change the way software is developed. To know more, send a mail to hello@knoldus.com or visit www.knoldus.com