If state is regarded as a bad idea for functions why is it regarded as okay have a state when you use a MailboxProcessor?
To expand, I was explaining functional programming to someone, how functions don't use state (no variables outside the function - i.e. same data out for same data in) and the good things that this brings. But then I got thinking about MailboxProcessor and the way it uses recursion to persist state between function calls, and I can't quite reconcile why it's okay in that situation.
Is it a case of it being the least bad way of persisting state?
The evil really is shared mutable state. In single-threaded case, shared mutable state means that functions cannot be safely composed - because one call can modify some state which is then read by a second call and so you'll get unexpected results. In multi-threaded case, shared mutable state means that you have potential for race conditions.
Functional programming generally avoids mutation. Functions can still share some state (e.g. closure can capture a state), but it cannot be mutated. In single-threaded case, there is also no non-determinism. In multi-threaded case, pretty much the only thing that you can do in pure functional style is to do fork-join parallelism (and data-parallelism) which does not need mutable state and is fully deterministic.
Agent-based programming also avoids shared mutable state, but in a different way. You have isolated agents that can only share immutable messages. So there is some non-determinism (because they communicate by sending messages), but they only exchange immutable values. In fact, you can even use mutable state inside an agent - as long as it is not shared, you still avoid shared mutable state.
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