在此SO post中添加
inSeq
|> Seq.length
|> printfn "%d lines read"
导致inSeq中的延迟序列被读入。
好的,我已扩展了该代码,并希望首先打印出该序列(请参阅下面的新程序)。
当Visual Studio(2012)调试器到达
时inSeq |> Seq.iter (fun x -> printfn "%A" x)
读取过程重新开始。当我使用调试器检查inSeq
时,inSeq
似乎没有元素。
如果我首先将元素读入inSeq
,我如何查看(检查)这些元素,以及为什么不通过调用Seq.iter
打印出来?
open System
open System.Collections.Generic
open System.Text
open System.IO
#nowarn "40"
let rec readlines () =
seq {
let line = Console.ReadLine()
if not (line.Equals("")) then
yield line
yield! readlines ()
}
[<EntryPoint>]
let main argv =
let inSeq = readlines ()
inSeq
|> Seq.length
|> printfn "%d lines read"
inSeq |> Seq.iter (fun x -> printfn "%A" x)
// This will keep it alive enough to read your output
Console.ReadKey() |> ignore
0
我在某处读过懒惰评估的结果没有缓存。那是怎么回事?如何缓存结果?
答案 0 :(得分:8)
序列不是项目的“容器”,而是在未来某个时间交付项目的“承诺”。您可以将其视为您调用的函数,除非它以块的形式返回结果,而不是一次性返回。如果您调用该函数一次,它会返回一次结果。如果你第二次打电话,它会第二次返回结果。
因为你的特定序列不纯,你可以将它与非纯函数进行比较:你调用它一次,它返回一个结果;你第二次称它,它可能会返回不同的东西。
序列在第一次读取后不会自动“记住”它们的项目 - 与第一次调用后函数不会自动“记住”它们的结果完全相同。如果你想从函数中获取它,你可以将它包装在一个特殊的“缓存”包装器中。所以你也可以做一个序列。
“缓存返回值”的一般技术通常称为“memoization”。特别是对于F#序列,它在Seq.cache
函数中实现。