Skip to content

Instantly share code, notes, and snippets.

@levinotik
Last active May 9, 2016 15:14
Show Gist options
  • Save levinotik/dd82dd1e785745070d83ce35cbe72ebd to your computer and use it in GitHub Desktop.
Save levinotik/dd82dd1e785745070d83ce35cbe72ebd to your computer and use it in GitHub Desktop.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment