Challenge 3: Why x + x's Substitutability Can't Be Guaranteed in Java — Possible Solution ==================================================================== // Referential transparency requires that an expression can be // replaced by its value with ZERO change in program behavior, no // matter where or when that substitution happens. For x + x to be // safely replaceable by "10" (given x = 5) EVERYWHERE, x's value must // be genuinely fixed for the entire time it's in scope -- there must // be no possible sequence of events that could make a later // evaluation of x see a different value than an earlier one did. // // In Java, a local variable declared without `final` can be // reassigned at any point after its declaration. Even if x happens to // equal 5 at the moment x + x first appears in the source code, there // is no guarantee that some other code -- running earlier in a // different branch, or (for a field rather than a local) from another // thread entirely -- hasn't changed x's value by the time a SECOND // reference to x is actually evaluated. The compiler cannot prove x // won't change between one use and the next, so it cannot guarantee // x + x always equals "value of x, doubled" as a fixed constant -- // the two occurrences of x in x + x are only guaranteed to see the // SAME value if nothing else in the entire program could possibly // have modified x in between, which Java's own mutable-by-default // variables never rule out. // // In Haskell, by contrast, x is bound once and can never be // reassigned by ANY code, anywhere, for as long as it's in scope -- // so there is no possible sequence of events that could make two // references to the same x see different values. That absolute // guarantee, which Java's mutable variables simply cannot offer, is // exactly what referential transparency requires. WHY THIS WORKS AS AN ANSWER ------------------------------ This correctly identifies that referential transparency requires a value to be genuinely unchangeable for the ENTIRE time it's in scope, and explains that Java's mutable-by-default variables can never rule out an intervening reassignment, which is exactly why the same substitution guarantee is impossible to make there.