【问题标题】:F# MailboxProcessor and Functional DesignF# MailboxProcessor 和功能设计
【发布时间】:2014-05-22 17:27:40
【问题描述】:
如果状态被认为是函数的坏主意,为什么当你使用 MailboxProcessor 时它被认为是好的?
为了扩展,我正在向某人解释函数式编程,函数如何不使用状态(函数外部没有变量 - 即相同的数据输出相同的数据)以及它带来的好处。但后来我开始考虑 MailboxProcessor 以及它使用递归在函数调用之间保持状态的方式,我不能完全调和为什么在这种情况下可以。
这是不是保持状态最不坏的方式?
【问题讨论】:
标签:
f#
functional-programming
mailboxprocessor
【解决方案1】:
真正的邪恶是共享可变状态。在单线程情况下,共享可变状态意味着无法安全地组合函数 - 因为一次调用可以修改某些状态,然后由第二次调用读取,因此您会得到意想不到的结果。在多线程情况下,共享可变状态意味着您有可能出现竞争条件。
函数式编程通常会避免变异。函数仍然可以共享一些状态(例如闭包可以捕获一个状态),但它不能被改变。在单线程情况下,也没有非确定性。在多线程的情况下,您可以在纯函数式风格中做的几乎唯一的事情就是执行不需要可变状态且完全确定性的 fork-join 并行(和数据并行)。
基于代理的编程也避免了共享可变状态,但方式不同。您拥有只能共享 不可变 消息的隔离代理。因此存在一些不确定性(因为它们通过发送消息进行通信),但它们只交换不可变的值。事实上,您甚至可以在代理内部使用可变状态 - 只要它不共享,您仍然可以避免共享可变状态。