F# 封装可变状态
我正在浏览F#Wikibook,我已经进入了关于参考单元格的部分,其中出现了以下代码片段:F# 封装可变状态,f#,F#,我正在浏览F#Wikibook,我已经进入了关于参考单元格的部分,其中出现了以下代码片段: let incr = let counter = ref 0 fun () -> counter := !counter + 1 !counter;; 然后调用此函数三次,分别给出值1、2和3。有人能解释一下为什么这个函数每次调用时不返回1吗?我解释这段代码的方式(这显然不是正确的解释,因此存在问题)是,首先声明引用单元格“counter”,其内容等
let incr =
let counter = ref 0
fun () ->
counter := !counter + 1
!counter;;
然后调用此函数三次,分别给出值1、2和3。有人能解释一下为什么这个函数每次调用时不返回1吗?我解释这段代码的方式(这显然不是正确的解释,因此存在问题)是,首先声明引用单元格“counter”,其内容等于0
,然后将“counter”的内容递增1,然后使用匿名函数取消引用。因为每次调用incr()
用内容0
声明“counter”,我不明白为什么要调用incr()代码>并不是每次都返回1
有人能纠正我的理解吗
提前感谢。当您调用incr()
时,您正在调用第3行的匿名函数incr
的值。调用的代码只是匿名函数,而不是incr
定义中的所有行
当定义了incr
时,计数器的初始化只执行一次,而不是每次调用incr
的值。这样想:incr
是一个值,而不是一个函数。它的值是捕获某些状态的闭包(即,计数器
)。该闭包随后可能被多次调用(incr
仅执行/分配一次)。也许看到同等的C#会有所帮助
static Func MakeCounter(){
int计数器=0;
return()=>{
计数器++;
返回计数器;
};
}
var incr=MakeCounter();
增量()//1.
增量()//2.
增量()//3.
“incr”是一个值而不是一个函数。
它实例化“counter”,然后绑定到内部函数(通过“counter”关闭)
调用“incr”实际上是调用内部函数计数器只声明和实例化一次。有趣的是,您可以在C#闭包中捕获可变变量counter
,然而,您需要在F#中显式地使计数器
成为一个堆分配的引用单元格。@JohnReynolds在这里看到一篇博文:以这种方式使用可变变量有时很难推理。强制使用引用单元格可以更清楚地了解发生了什么。