I'm studying programming language theory and I can't figure out a solid reason why lazy languages don't have mutation. Anyone know the reason?
Mutation means you cannot be sure of the state of the program at any time and will have to worry about side effects from any action. I've actually thought about it and I can't think of any way to have a completely lazy language that supports mutation. (I am no computer scientist though.)
Laziness means that a function is not actually evaluated until (or unless) its return value is used. This means that function calls aren't necessarily evaluated in the order in which they appear in the code. It also means that there can't be void-functions because they would never be evaluated (as its not possible to use a return value that does not exist).
However for functions that perform side-effects (like mutation, but also just printing to the screen) it does matter in which order they're executed. It matters even more that they're executed at all. This means that lazy languages need a way to emulate side-effects in special types that ensure that they are executed and executed in the right order.
Since entirely side effect-free programs are useless (you need to be able to print to the screen at all), lazy languages actually do support side-effect. They just encapsulate them with the IO monad or uniqueness-types. As an example haskell does have mutable arrays, but they can be only used inside the IO monad.