F# MailboxProcessor and Functional Design
Asked Answered
S

1

8

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?

Syndic answered 9/4, 2014 at 13:18 Comment(0)
D
14

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.

Disruption answered 9/4, 2014 at 13:34 Comment(1)
more on actor state and non-determinism here and hereTowery

© 2022 - 2024 — McMap. All rights reserved.