Is my understanding of "referential transparency" of mutable classes correct?

From the book "Functional Programming in Scala" I see the definition of a "referential transparent" expression:

An expression e is referentially transparent if, for all programs p, all occurrences of e in p can be replaced with the result of evaluating e without affecting the value of p.

I have code examples that I'm not sure if they are referentially transparent or not.

I will use scala.collection.mutable.StringBuilder

in examples which are mutable class

1.

val x = new StringBuilder("Hello")

println(x.length)
println(x.length)

      

Let's assume the code here is complete and complete code that uses x

.

Can I say that the expression x

is a referential transparent expression?

If I change everything x

with its value new StringBuilder("Hello")

, the observed behavior of the program does not change:

val x = new StringBuilder("Hello")

println(new StringBuilder("Hello").length)
println(new StringBuilder("Hello").length)

      

2.

val x = new StringBuilder("Hello")
val y = x.append("aaa")

      

Let's assume the code here is complete and complete code that uses x

and y

.

Is it safe to say which y

is referential transparent because it is not used at all in the program?

3.

def getTheClassName(n:Int):String = {
  val x = new StringBuilder("hello")
  for(int i=0;i<n;i++) {
    x.append("world")
  }
  return x.getClass.getName
}

      

Can you tell what x

is referential transparent? Because no matter how I replace it with my value, the return value will not be changed.

PS: Maybe the main problem is that I don't understand what it means for all programs p

, does the existing complete code mean? Or any possible code to add?

+3


source to share


2 answers


This means that for any possible program, p

you can write an expression containing this. This must be correctly defined in relation to the language or set of possible programs. Thus, yours x

is referentially transparent in the language in which the only program that works is the one you wrote. Yours y

is referentially transparent in a subset of Scala where you are not allowed to call .append

on StringBuilder

. But these are not particularly interesting languages ​​to talk about.

Most of the time people talk about a "referentially transparent" expression, they (implicitly) mean something like a safe subset of Scalazzi Scala , which is general enough to express (all?) Useful Scala programs, but safe enough to reason about. Because, of course, if you are allowed to call, for example. System.identityHashCode()

, most supposedly "referentially transparent" expressions are not actually.



Of course, the most important definition is operational; what is "referentially transparent" ultimately depends on what you want to use it for. One important use case is compiler / library optimization: we do not want the compiler to do the substitution shown in example 1, because for most programs this "optimization" would change the meaning of the program. But we're glad the compiler optimizes our programs by inlining immutable constants, because our programs "don't have to" depend on what is identityHashCode

for a particular constant.

+2


source


As I understand it, the expression "e" is referentially transparent, it is referentially transparent to all possible "p" programs.

It may be "referentially transparent" for a particular "p" program, but if you can write another "px" program that violates the "replacement rule", that means the expression is not referentially transparent.

  import scala.collection.mutable

  val b = new mutable.StringBuilder("Hello")
  def e = b.length

  def p0 = {
    val l1 = e
    val l2 = e
    l1 + l2
  }

  def p1 = {
    val l1 = e
    b.append("World")
    val l2 = e
    l1 + l2
  }

      



It is possible to create a program "p" that will violate "e in p, can be replaced by the result of evaluating e" - this means that "e" is not referentially transparent. With mutable state, it is very easy to build this program.

At p0, one can say that e is referential transparent, but p1 breaks it down easily.

+1


source







All Articles