Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 封装可变状态_F# - Fatal编程技术网

F# 封装可变状态

F# 封装可变状态,f#,F#,我正在浏览F#Wikibook,我已经进入了关于参考单元格的部分,其中出现了以下代码片段: let incr = let counter = ref 0 fun () -> counter := !counter + 1 !counter;; 然后调用此函数三次,分别给出值1、2和3。有人能解释一下为什么这个函数每次调用时不返回1吗?我解释这段代码的方式(这显然不是正确的解释,因此存在问题)是,首先声明引用单元格“counter”,其内容等

我正在浏览F#Wikibook,我已经进入了关于参考单元格的部分,其中出现了以下代码片段:

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在这里看到一篇博文:以这种方式使用可变变量有时很难推理。强制使用引用单元格可以更清楚地了解发生了什么。