F# 返回带有闭包的函数
以下代码:F# 返回带有闭包的函数,f#,F#,以下代码: let CreateFunc= let counter = ref 0 fun () -> counter := !counter + 1; !counter let f1 = CreateFunc let f2 = CreateFunc printfn "%d" (f1()) printfn "%d" (f1()) printfn "%d" (f2()) printfn "%d" (f2()) 产出: 1 2 3 4 所以,基本上,我们在这里看到的是f
let CreateFunc=
let counter = ref 0
fun () -> counter := !counter + 1; !counter
let f1 = CreateFunc
let f2 = CreateFunc
printfn "%d" (f1())
printfn "%d" (f1())
printfn "%d" (f2())
printfn "%d" (f2())
产出:
1
2
3
4
所以,基本上,我们在这里看到的是f1和f2是同一个函数——因为它们显然共享同一个“counter”实例
预期产出为:
1
2
1
2
问:f1和f2不应该是两个独立的实例吗?毕竟,它们是由对“CreateFunc”的两个不同调用创建的
谢谢
输出为
1
2
1
2
说明:
在最初的解决方案中,CreateFunc
是一个函数,但始终是同一个函数(CreateFunc
、f1
和f2
都是同义词,都指向同一个函数)。在我的解决方案中,CreateFunc
是一个函数,每当调用它时,它都会返回一个新的函数,因此每个函数都有自己的状态(即计数器
)
简而言之:原始的
CreateFunc
是一个值,始终是相同的值。@swapneel-:=
是将值分配给引用单元格的方式(在本例中是使用ref 0
创建的)。此代码使用!计数器
读取引用单元格中的值。为了详细说明@JoelMueller的答案:由于常规let绑定是不可变的,当您确实想使用可变绑定(并且let mutable
有其缺点)时,您可以使用ref
类型,这有点类似于C/C++指针(只有一点)。要获得它们的值,可以使用代码>前缀运算符(如代码!计数器)和分配,您可以使用二进制运算符:=
(代码计数器中的行:=!计数器+1
)。注意:自<代码>计数器:=!计数器+1
很常见,有一个incr
函数(使用incr counter
)将int ref
增加一个。为了详细说明@Ramon Snir的答案,闭包中不允许使用普通可变项,因此这里必须使用ref单元格。
1
2
1
2