5

我在代码中遇到了一个错误,这让我觉得我并不真正了解有关 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

当我在 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

这让我觉得这getStringFromFile是在懒惰地评估——所以我完全糊涂了。我对 F# 如何评估函数一无所知。

4

2 回答 2

10

为了快速解释正在发生的事情,让我们从这里开始:

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. 但是看看在分配你的变量和返回它之间发生了什么:你关闭了你的流。

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

并且不要忘记通过声明use whatever = ...而不是let whatever = ....

考虑到这一点,这里有一个修复:

let getStringFromFile() =  
    use s = File.OpenRead(@"c:\eo\raw.txt")
    use r = new StreamReader(s)
    r.ReadToEnd()
于 2010-09-15T17:42:55.027 回答
2

You don't read from your file. You bind method ReadToEnd of your instance of StreamReader to the value data and then call it when you call getStringFromFile(). The problem is that the stream is closed at this moment.

I think you have missed the parentheses and here's the correct version:

// 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
于 2010-09-15T17:50:06.460 回答