2016-09-27 5 views
1

В этом 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 

Я где-то читал, что результаты ленивой оценки не кэшируются. Это то, что здесь происходит? Как кешировать результаты?

+6

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

+0

Где я буду использовать это и почему? – octopusgrabbus

+0

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

ответ

8

Последовательность не является «контейнером» предметов, а скорее «обещанием» доставлять товары в будущем. Вы можете думать об этом как о функции, которую вы вызываете, за исключением того, что она возвращает результат в кусках, а не все одновременно. Если вы вызываете эту функцию один раз, она возвращает результат один раз. Если вы вызовете его второй раз, он вернет результат во второй раз.

Поскольку ваша конкретная последовательность не является чистой, вы можете сравнить ее с нечистой функцией: вы вызываете ее один раз, она возвращает результат; вы называете это второй раз, он может вернуть что-то другое.

Последовательности автоматически не «запоминают» их элементы после первого считывания - точно так же, как функции не автоматически «запоминают» их результат после первого вызова. Если вы хотите это от функции, вы можете обернуть ее в специальную «кэширующую» оболочку. И так вы можете сделать и для последовательности.

Общая методика «кэширования возвращаемого значения» обычно называется «memoization». В частности, для последовательностей F # он реализован в функции Seq.cache.

+0

Спасибо за ваш ответ. Какую собственную структуру данных F # следует использовать вместо последовательности, чтобы можно было добавить ее в структуру, и сохранить ее содержимое для большей обработки? – octopusgrabbus

+0

«Список», возможно? Это действительно зависит от конкретного использования, разные структуры данных будут иметь разную производительность и характеристики памяти. –

+0

Спасибо. @FyodorSoikin Я тоже думаю, список. – octopusgrabbus

 Смежные вопросы

  • Нет связанных вопросов^_^