来自流阅读器的F#懒惰评估? [英] F# lazy eval from stream reader?

查看:78
本文介绍了来自流阅读器的F#懒惰评估?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在代码中遇到一个错误,使我认为我不太了解有关F#和惰性评估的某些细节.我知道F#会急切地求值,因此会因以下功能而感到困惑:

I'm running into a bug in my code that makes me think that I don't really understand some of the details about F# and lazy evaluation. I know that F# evaluates eagerly and therefore am somewhat perplexed by the following function:

// 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#如何评估函数一无所知.

This makes me think that getStringFromFile is being evaluated lazily--so I'm totally confused. I'm not getting something about how F# evaluates functions.

推荐答案

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

For a quick explanation of what's happening, lets start here:

let getStringFromFile =  
    File.OpenRead("c:\\eo\\raw.txt")
    |> fun s -> let r = new StreamReader(s)
                let data = r.ReadToEnd
                r.Close()
                s.Close()
                data

您可以将函数的前两行重写为:

You can re-write the first two lines of your function as:

let s = File.OpenRead(@"c:\eo\raw.txt")

接下来,您已经省略了此方法的括号:

Next, you've omitted the parentheses on this method:

            let data = r.ReadToEnd
            r.Close()
            s.Close()
            data

因此,data具有类型unit -> string.当您从函数中返回该值时,整个结果为unit -> string.但是看看分配变量和返回变量之间发生了什么:关闭流.

As a result, data has the type unit -> string. When you return this value from your function, the entire result is unit -> string. But look what happens in between assigning your variable and returning it: you closed you streams.

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

End result, when a user calls the function, the streams are already closed, resulting in the error you're seeing above.

也不要忘记通过声明use whatever = ...而不是let whatever = ...来处置对象.

And don't forget to dispose your objects by declaring use whatever = ... instead of let whatever = ....

牢记这一点,这里有个解决方法:

With that in mind, here's a fix:

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

这篇关于来自流阅读器的F#懒惰评估?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆