In his 1992 thesis, Alan Bawden wonderfully describes why it’s so hard to pin down the meaning of “state” in programming:
In cases where state cannot be eliminated, it behaves much like a bump in a rug that won’t go away. Flatten the bump out in one place, and some other part of the rug bulges up. Any part of the rug can be made locally flat, but some global property (perhaps the rug is too large for the room) makes it impossible for the entire rug to be flat simultaneously. Analogously, we may be able to describe all the components of a system in stateless terms, but when the components are assembled together, some components will perceive other components as possessing state.
As an example, consider the simple system consisting of a programmer interacting, via a keyboard and display, with a computer. Imagine that the software running on the computer is written entirely in a functional programming language, the stream of output sent to the display is expressed as a function of the stream of keyboard input. […] Thus the description of the subsystem consisting of the keyboard, computer and display is entirely free of any mention of state, yet from the programmer’s viewpoint, as he edits a file, the computer certainly appears to have state.
Imagine further that the programmer is actually a robot programmed in a functional language, his stream of keystrokes is expressed as a function of the stream of images he sees. Now the situation appears symmetrical with respect to the programmer and computer, and the computer can claim that it is the programmer that is the component of the system that has state.
All components in this system agree that from their perspective there is state somewhere else in the system, but since each component is itself described in state-free terms, there is no component that can be identified as the location of that state. This does not mean that the phenomenon of state is any less real than it would be if we could assign it a location. It does mean that we have to be careful about treating state as anything other than a perceptual phenomenon experienced by some components in their interaction with other components.
(From Linear Graph Reduction: Confronting the Cost of Naming, §6.1, pp. 108-109)
This is similar to the point I tried to make in Immutability is not Enough. The notion of state is trickier than it seems, and while functional programming can help, I’m pretty sure it’s not the silver bullet that so many people want it to be.
See also: The C language is purely functional by Conal Elliot.