2016-09-27 2 views
1

In dieser SO post, das HinzufügenWarum löst das Iterieren einer zuvor eingelesenen Sequenz einen neuen Lesevorgang aus?

inSeq 
    |> Seq.length 
    |> printfn "%d lines read" 

die faule Sequenz in inSeq verursacht in gelesen werden.

OK, ich habe auf diesem Code erweitert und will zunächst aus dieser Sequenz drucken (siehe neu Programm unten).

Wenn das Visual Studio (2012) Debugger bekommt zu

inSeq |> Seq.iter (fun x -> printfn "%A" x) 

der Lesevorgang beginnt von neuem. Wenn ich inSeq mit dem Debugger untersuche, scheint inSeq keine Elemente darin zu haben.

Wenn ich zuerst Elemente in inSeq gelesen habe, wie kann ich diese Elemente sehen (untersuchen) und warum werden sie nicht mit dem Aufruf Seq.iter ausgedruckt?

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 

Ich habe irgendwo gelesen, dass Ergebnisse der faulen Bewertung nicht zwischengespeichert werden. Geht das hier? Wie kann ich die Ergebnisse zwischenspeichern?

+6

['Seq.cache'] (https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/seq.cache%5B't%5D-funktion-%5Bfsharp%5D)? –

+0

Wo werde ich das verwenden und warum? – octopusgrabbus

+0

'let inSeq = readlines() |> Seq.cache' –

Antwort

8

Sequence ist kein "Container" von Artikeln, sondern vielmehr ein "Versprechen", Artikel irgendwann in der Zukunft zu liefern. Sie können es sich als eine Funktion vorstellen, die Sie aufrufen, außer dass es sein Ergebnis in Chunks zurückgibt, nicht auf einmal. Wenn Sie diese Funktion einmal aufrufen, erhalten Sie das Ergebnis einmal zurück. Wenn Sie das zweite Mal anrufen, wird das Ergebnis das zweite Mal zurückgegeben.

Da Ihre bestimmte Sequenz nicht rein ist, können Sie sie mit einer nicht-reinen Funktion vergleichen: Sie rufen sie einmal auf, sie gibt ein Ergebnis zurück; Sie nennen es das zweite Mal, es kann etwas anderes zurückgeben.

Sequenzen "erinnern" sich nicht automatisch nach dem ersten Lesevorgang - genauso wie sich Funktionen nach dem ersten Aufruf nicht automatisch an ihr Ergebnis "erinnern". Wenn Sie das von einer Funktion möchten, können Sie es in einen speziellen "Caching" -Wrapper einfügen. Und so können Sie auch für eine Sequenz tun.

Die allgemeine Technik des "Caching Rückgabewerts" wird üblicherweise "memoization" genannt. Insbesondere für F # -Sequenzen ist es in der Funktion Seq.cache implementiert.

+0

erkennen Danke für Ihre Antwort. Welche native F # -Datenstruktur sollte anstelle einer Sequenz verwendet werden, um die Struktur hinzufügen zu können, und ihre Inhalte für eine weitere Verarbeitung verfügbar zu halten? – octopusgrabbus

+0

'List' vielleicht? Es hängt wirklich von der spezifischen Verwendung ab, unterschiedliche Datenstrukturen haben unterschiedliche Leistungs- und Speichereigenschaften. –

+0

Danke. @FyodorSoikin Ich denke auch Liste. – octopusgrabbus

Verwandte Themen