Reading "Functional Programming in Scala" and I'm a little confused by the section on exceptions not being referentially transparent.
The example given is
def failingFn(i: Int): Int = {
val y: Int = throw new Exception("fail!")
try {
val x = 42 + 5
x + y
}
catch { case e: Exception => 43 }
}
So the argument given in the book is that y
is not referentially transparent because if we substitute it into the body in the try
block we get a different result than if just run the function directly. This doesn't make any sense to me because the entire function is non-terminating to begin with so what is the point of saying values within the function body are not referentially transparent? The naive substitution in my mind would be as follows
def failingFn(i: Int): Int = {
val y: Int = throw new Exception("fail!")
try {
val x = 42 + 5
x + ((throw new Exception("fail!")): Int)
}
catch { case e: Exception => 43 }
}
and that still fails with the same exception.
Moreoever, y
itself is a non-value (it can't directly be evaluated to a value) so what is the point of talking about referential transparency for such expressions? I suspect there is some kind of sleight of hand going on here so where exactly is my reasoning incorrect?
Referential transparency means you can take an expression in your program, and replace it with the result of that expression. As an example, if you have the expression 5+4, you can replace that with 9. That's what it means. Now 5+4 is easy because you can do that in your head without running the program.
Referential Transparency Benefit #1: RefactoringIf we can determine that an expression is referentially transparent, we can quickly replace it with the value it produces, and vice-versa. Some examples follow. Referential transparency is basically a fancy term for “replaceable code”.
The importance of referential transparency is that it allows the programmer and the compiler to reason about program behavior as a rewrite system.
Another benefit of referential transparency is that it eliminates side-effects from your code. Referential transparency requires that functions be free of any code that can modify the program state outside of the function.
The point being made in the book is that, if it were truly referentially transparent, then you can remove the y
variable entirely and replace it inside of the try/catch
and you end up with different semantics.
So, the point being made is that, in the case of exceptions, the point of evaluation for an exception matters.
Maybe you can argue that the two programs are not semantically the same because of the location of the evaluation is what actually matters here. If you make the y
lazy
, then the outcomes do not change.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With