Comment by fpoling
Pure languages still use stack to store mutating state. In a single-threaded programs this is almost non-observable except for occasional stack overflow crashes. But with multiple threads and message passing one can emulate arbitrary state mutation just by using messages and stack.
Then I have found the code that is a heavy user of closures is harder to understand even if it is single-threaded and closures can pass arbitrary state even if the state is immutable.
What I have found useful is persistent data structures. Those really simplify modelling. But then those can be used in imperative languages as well.