F# 为什么按顺序迭代以前的读取会触发新的读取?

F# 为什么按顺序迭代以前的读取会触发新的读取?,f#,seq,F#,Seq,在本条中,加入 导致读入inSeq中的惰性序列 好的,我已经对代码进行了扩展,希望首先打印出那个序列(见下面的新程序) 当Visual Studio(2012)调试器到达 inSeq |> Seq.iter (fun x -> printfn "%A" x) 读取过程重新开始。当我使用调试器检查inSeq时,inSeq中似乎没有任何元素 如果我先将元素读入inSeq,我如何才能看到(检查)这些元素,为什么不调用Seq.iter open System open System.Col

在本条中,加入

导致读入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
开放系统
open System.Collections.Generic
开放系统.Text
开放系统
#诺瓦恩“40”
让rec读取行()=
序号{
let line=Console.ReadLine()
如果不是(第行等于(“”),则
生产线
yield!readlines()
}
[]
让主argv=
设inSeq=readlines()
inSeq
|>序号长度
|>printfn已读取%d行
inSeq |>Seq.iter(乐趣x->printfn“%A”x)
//这将使它保持足够的活力,以读取您的输出
Console.ReadKey()|>忽略
0
我在某个地方读到,延迟计算的结果不会被缓存。这是怎么回事?如何缓存结果?

序列不是项目的“容器”,而是将来某个时候交付项目的“承诺”。您可以将其视为一个调用的函数,除非它以块的形式返回结果,而不是一次返回所有结果。如果调用该函数一次,它将返回一次结果。如果您再次调用它,它将再次返回结果

因为您的特定序列不是纯的,所以您可以将其与非纯函数进行比较:您调用它一次,它将返回一个结果;如果你第二次调用它,它可能会返回不同的结果

序列在第一次读取后不会自动“记住”它们的项,这与函数在第一次调用后不会自动“记住”它们的结果完全相同。如果您想从函数中获得这些信息,可以将其包装在一个特殊的“缓存”包装器中。所以你也可以做一个序列

“缓存返回值”的一般技术通常称为“”。特别是对于F#序列,它是在函数中实现的。

序列不是项目的“容器”,而是在将来某个时候交付项目的“承诺”。您可以将其视为一个调用的函数,除非它以块的形式返回结果,而不是一次返回所有结果。如果调用该函数一次,它将返回一次结果。如果您再次调用它,它将再次返回结果

因为您的特定序列不是纯的,所以您可以将其与非纯函数进行比较:您调用它一次,它将返回一个结果;如果你第二次调用它,它可能会返回不同的结果

序列在第一次读取后不会自动“记住”它们的项,这与函数在第一次调用后不会自动“记住”它们的结果完全相同。如果您想从函数中获得这些信息,可以将其包装在一个特殊的“缓存”包装器中。所以你也可以做一个序列


“缓存返回值”的一般技术通常称为“”。特别是对于F序列,它是在函数中实现的。

?我将在哪里使用它,为什么?
让inSeq=readlines()|>Seq.cache
Seq
本质上是一个
IEnumerable
。就像C#,每次迭代都会重新启动迭代器。当编译器或Resharper检测到一个
IEnumerable
的多次迭代时,实际上会发出警告?我将在哪里使用它,为什么使用它?
让inSeq=readlines()|>Seq.cache
Seq本质上是一个
IEnumerable
。就像C#,每次迭代都会重新启动迭代器。编译器或Resharper在检测到一个
IEnumerable
的多次迭代时实际上会发出警告,谢谢您的回答。应该使用什么本机F#数据结构来代替序列,以便能够添加到结构中,并保留其内容以进行更多处理?
List
?这取决于具体的用途,不同的数据结构会有不同的性能和内存特性。谢谢@FyodorSoikin我也在考虑列表。提醒一句:不要试图通过反复添加项目或类似的内容来构建列表。只需按顺序使用
Seq.toList
。重复将项目添加到列表中会发生什么?谢谢您的回答。应该使用什么本机F#数据结构来代替序列,以便能够添加到结构中,并保留其内容以进行更多处理?
List
?这取决于具体的用途,不同的数据结构会有不同的性能和内存特性。谢谢@FyodorSoikin我也在考虑列表。提醒一句:不要试图通过反复添加项目或类似的内容来构建列表。只需获取序列并在其上使用
Seq.toList
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