简体   繁体   中英

F# MailboxProcessor and Functional Design

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 - ie 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 (eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM