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#_Evaluation_Lazy Evaluation_Eager - Fatal编程技术网

F#流读取器的懒惰评估?

F#流读取器的懒惰评估?,f#,evaluation,lazy-evaluation,eager,F#,Evaluation,Lazy Evaluation,Eager,我在代码中遇到了一个bug,这让我觉得我不太了解F#和懒惰评估的一些细节。我知道F#求值很快,因此对以下函数有些困惑: // Open a file, then read from it. Close the file. return the data. let getStringFromFile = File.OpenRead("c:\\eo\\raw.txt") |> fun s -> let r = new StreamReader(s)

我在代码中遇到了一个bug,这让我觉得我不太了解F#和懒惰评估的一些细节。我知道F#求值很快,因此对以下函数有些困惑:

// Open a file, then read from it. Close the file. return the data.
let getStringFromFile =  
    File.OpenRead("c:\\eo\\raw.txt")
    |> fun s -> let r = new StreamReader(s)
                let data = r.ReadToEnd
                r.Close()
                s.Close()
                data
// Open a file, then read from it. Close the file. return the data.
let getStringFromFile =  
    File.OpenRead("c:\\eo\\raw.txt")
    |> fun s -> let r = new StreamReader(s)
                let data = r.ReadToEnd()
                r.Close()
                s.Close()
                data
当我在FSI中称之为:

> let d = getStringFromFile();;

System.ObjectDisposedException: Cannot read from a closed TextReader.

at System.IO.__Error.ReaderClosed()
at System.IO.StreamReader.ReadToEnd()
at <StartupCode$FSI_0134>.$FSI_0134.main@()
Stopped due to error
>设d=getStringFromFile();;
System.ObjectDisposedException:无法从关闭的文本读取器读取。
在System.IO.\u Error.ReaderClosed()处
在System.IO.StreamReader.ReadToEnd()中
地址:$FSI_0134.main@()
由于错误而停止

这让我觉得
getStringFromFile
的计算很慢,所以我完全搞不清楚。我不了解F#如何计算函数。

要快速解释发生了什么,让我们从这里开始:

let getStringFromFile =  
    File.OpenRead("c:\\eo\\raw.txt")
    |> fun s -> let r = new StreamReader(s)
                let data = r.ReadToEnd
                r.Close()
                s.Close()
                data
您可以将函数的前两行重写为:

let s = File.OpenRead(@"c:\eo\raw.txt")
接下来,您省略了此方法中的括号:

            let data = r.ReadToEnd
            r.Close()
            s.Close()
            data
因此,
data
的类型为
unit->string
。从函数返回此值时,整个结果是
unit->string
。但看看在分配变量和返回变量之间发生了什么:您关闭了流

最终结果是,当用户调用该函数时,流已经关闭,导致上面看到的错误

不要忘记通过声明
使用which=…
而不是
让which=…
来处理对象

考虑到这一点,这里有一个解决方案:

let getStringFromFile() =  
    use s = File.OpenRead(@"c:\eo\raw.txt")
    use r = new StreamReader(s)
    r.ReadToEnd()

您没有读取您的文件。将
StreamReader
实例的方法
ReadToEnd
绑定到值
data
,然后在调用
getStringFromFile()
时调用它。问题是,这条河此时关闭了

我想你错过了括号,下面是正确的版本: