F#流读取器的懒惰评估?
我在代码中遇到了一个bug,这让我觉得我不太了解F#和懒惰评估的一些细节。我知道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)
// 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()
时调用它。问题是,这条河此时关闭了
我想你错过了括号,下面是正确的版本: