scalafunctional-programmingreferential-transparency

Does return break referential transparency?


I was reading the description of the Scala WartRemover tool, and was confused by one of the points they had. The description said this:

return breaks referential transparency. Refactor to terminate computations in a safe way.

// Won't compile: return is disabled
def foo(n:Int): Int = return n + 1
def foo(ns: List[Int]): Any = ns.map(n => return n + 1)

This doesn't make any sense to me, and both of the examples look referentially transparent. Is there some way in which the return keyword makes it any more likely for a function to break referential transparency? Am I just completely misunderstanding their point?


Solution

  • At it's core, referentially transparency is about evaluating expressions. Fundamentally, it says that if you evaluate an expression in a context, it will evaluate to the same value if you evaluate it in any identical context.

    Except that "return" statements don't evaluate to anything at all. They cause the current call of the enclosing method to evaluate to something. There's no way that fits the concept of referential transparency. The "throw" statement has a similar problem.

    For the examples, the first one

    def foo(n:Int): Int = return n + 1
    

    is benign but verbose and non-idiomatic. The second one

    def foo(ns: List[Int]): Any = ns.map(n => return n + 1)
    

    is much more problematic. If passed the empty list, it returns the empty list. If passed a non empty list, it returns the value of the head of the list plus 1.