我试图了解F#中的Closure。基于问题和答案here我的理解是,它是承载上下文的过程。其中一个答案有一个非常简单的解决方案,如下面的
let addCounter =
let counter = ref 0
(fun () -> incr counter; !counter)
[<EntryPoint>]
let main argv =
let firstCounter = addCounter()
printfn "%A" firstCounter
printfn "%A" firstCounter
let k = Console.ReadKey()
我创建了一个名为firstCounter的高阶函数,我期望第一个输出为1,第二个输出为2.但是当我运行时,我得到的答案都是1.这是我在这里做错了吗?
答案 0 :(得分:5)
尝试运行:
let addCounter =
let counter = ref 0
(fun () -> incr counter; !counter)
[<EntryPoint>]
let main argv =
printfn "%d" (addCounter ())
printfn "%d" (addCounter ())
let k = Console.ReadKey()
您的版本执行此操作:它会调用addCounter
一次,并将结果值1
分配给firstCounter
- 所以当您评估firstCounter
时,您会得到相同的答案(这实际上只是一个整数)多次。
具有闭包的部分是函数counter
捕获fun () -> incr counter; !counter
并且在F#中使用它是一个相当普遍的事情(如果你可以使用闭包,他们需要类来捕获状态 - 确实类(及其方法)和闭包有很多共同之处!
如果你想动态创建计数器,你可以这样做:
let createCounter() =
let counter = ref 0
(fun () -> incr counter; !counter)
[<EntryPoint>]
let main argv =
let c1 = createCounter()
let c2 = createCounter()
printfn "%d" (c1 ()) // -> "1"
printfn "%d" (c2 ()) // -> "1"
printfn "%d" (c1 ()) // -> "2"
printfn "%d" (c1 ()) // -> "3"
printfn "%d" (c2 ()) // -> "2"
现在每当你调用createCounter
时,都会创建一个新的ref
- 单元格,并且会返回一个增加并返回此函数的函数 - 所以每次调用都会得到一个带有上下文的新计数器,你可以使用它那些在你之前使用addCounter
的那些