An expression is said to be referentially transparent if it can be replaced with its value without changing the behavior of a program (in other words, yielding a program that has the same effects and output on the same input)
https://en.wikipedia.org/wiki/Referential_transparency
This example is taken from the book "Functional Programming in Scala"
The following is referentially transparent:
scala> val x = "hello, world"
x: String = hello, world
scala> val r1 = x.reverse
r1: String = dlrow ,olleh
scala> val r2 = x.reverse
r2: String = dlrow ,olleh
Referential transparency means that we can replace all occurrences of r2 and r1 with the expression x.reverse
and it would have no effect on our program.
r4, in the following example, replaces r1 and r2 with x.reverse. This substitution has no effect on our program. This demonstrates that the .reverse function is a pure function.
scala> val r3 = r1 + r2
r3: String = dlrow ,ollehdlrow ,olleh
scala> val r4 = x.reverse + x.reverse
r4: String = dlrow ,ollehdlrow ,olleh
scala> r4 == r3
res0: Boolean = true
Let's try another example:
scala> val x = new StringBuilder("hello")
x: StringBuilder = hello
scala> val y = x.append(", world")
y: StringBuilder = hello, world
scala> val r1 = y.toString
r1: String = hello, world
scala> val r2 = y.toString
r2: String = hello, world
scala> r1 == r2
res1: Boolean = true
So far so good. r1 and r2 are equivalent. If the expression x.append(", world")
were referentially transparent, it would mean that we could replace all occurrences of the variable y with
that expression and produce an equivalent program.
Let's see what happens when we do that.
scala> val r1 = x.append(", world").toString
r1: String = hello, world, world
scala> val r2 = x.append(", world").toString
r2: String = hello, world, world, world
scala> r1 == r2
res2: Boolean = false
We no longer have referential transparency because StringBuilder#append is not a pure function.
It mutates the object referenced by x
. Earlier we used y.toString
. Here, we replaced y with the expression referenced by y
which is x.append(", world")
. The substitution results in a different program.