【发布时间】:2015-08-08 17:45:25
【问题描述】:
我有一些 F# 代码可以缓存结果以供将来查找。我的理解是,您添加的字典和其他数据结构需要副作用。 (即改变字典的状态)这是正确的吗?这被认为是不纯的还是仍然在无副作用计算的模型中。
let rec fib =
let dict = new System.Collections.Generic.Dictionary<_,_>()
fun n ->
match dict.TryGetValue(n) with
| true, v -> v
| false, _ ->
let fibN =
match n with
| 0 | 1 -> n
| _ -> fib (n - 1) + fib(n - 2)
dict.Add(n, fibN)
fibN
【问题讨论】:
-
我的 F# 可能有点生锈,但我看不出对
fib的连续调用如何共享dict的实例以提供缓存。函数的每个调用不是都有自己的dict实例吗? -
@CoderDennis 它是对字典的闭包。 fib 一词与执行逻辑的 lamda 函数绑定。每个调用共享 dict 绑定
-
副作用的问题在于范围和推理系统如何运作的能力。这就是为什么全局变量是终极邪恶的原因。 fib 函数本身没有副作用。它在实现中具有副作用的事实是无关紧要的。
-
@mydogisbox 不会 dict.TryGetValue(n) 容易受到副作用的影响。不是在这个例子中,而是在一般情况下。因为内存中某个地方的状态会影响运行时值。例如,如果我在第一次调用时在 dict 中存储了错误的值,但返回了正确的值。我第二次调用它时会得到错误的值。
-
@TomDDD:如果(实际)函数是纯函数,则不能在 dict 中存储错误的值,因为对于给定的 arg,函数只能产生一个值。
标签: f# functional-programming memoization side-effects