Недостаточно в вашем понимании, что F # Seq
равно ленивый .Он не будет выполнять больше работы, чем необходимо, и, в частности, он не будет использовать последовательность, пока это не станет абсолютно необходимым.В частности, Seq.map
и Seq.filter
не действуют как циклы;вместо этого они действуют как конвейер преобразования, который укладывает новое преобразование поверх существующих.Первый фрагмент вашего кода, который фактически будет проходить через весь внешний вид, - это Seq.sortBy
(поскольку для сортировки последовательности необходимо знать, каковы все ее значения, поэтому Seq.sortBy
должен использовать всю последовательность для выполнения своей работы).И к этому моменту шаг Seq.filter
уже произошел, так много строк файла CSV было выброшено, и поэтому программа потребляет меньше памяти, чем общий размер исходного файла.
Вотпрактическая демонстрация ленивости Seq
, введенной в F # Interactive.Посмотрите это:
> let s = seq {1..20} ;;
val s : seq<int>
> let t = s |> Seq.map (fun i -> printfn "Starting with %d" i; i) ;;
val t : seq<int>
> let u = t |> Seq.map (fun i -> i*2) ;;
val u : seq<int>
> let v = u |> Seq.map (fun i -> i - 1) ;;
val v : seq<int>
> let w = v |> Seq.filter (fun i -> i > 10) ;;
val w : seq<int>
> let x = w |> Seq.sortBy id ;;
val x : seq<int>
> let y = x |> Seq.iter (fun i -> printfn "Result: %d" i) ;;
Starting with 1
Starting with 2
Starting with 3
Starting with 4
Starting with 5
Starting with 6
Starting with 7
Starting with 8
Starting with 9
Starting with 10
Starting with 11
Starting with 12
Starting with 13
Starting with 14
Starting with 15
Starting with 16
Starting with 17
Starting with 18
Starting with 19
Starting with 20
Result: 11
Result: 13
Result: 15
Result: 17
Result: 19
Result: 21
Result: 23
Result: 25
Result: 27
Result: 29
Result: 31
Result: 33
Result: 35
Result: 37
Result: 39
val y : unit = ()
> let z = w |> Seq.iter (fun i -> printfn "Result: %d" i) ;;
Starting with 1
Starting with 2
Starting with 3
Starting with 4
Starting with 5
Starting with 6
Result: 11
Starting with 7
Result: 13
Starting with 8
Result: 15
Starting with 9
Result: 17
Starting with 10
Result: 19
Starting with 11
Result: 21
Starting with 12
Result: 23
Starting with 13
Result: 25
Starting with 14
Result: 27
Starting with 15
Result: 29
Starting with 16
Result: 31
Starting with 17
Result: 33
Starting with 18
Result: 35
Starting with 19
Result: 37
Starting with 20
Result: 39
val z : unit = ()
Обратите внимание, что хотя Seq.sortBy
необходимо использовать весь список, чтобы выполнить свою работу, поскольку ни одна часть Seq
не запрашивалась при создании последовательности x
на самом деле он не начал работать через значения.Только последовательности y
и z
, которые использовали Seq.iter
, фактически запускали прогон всех значений.(Но вы можете видеть, как при y
шаг sortBy
должен был выполняться полностью до того, как мог выполняться шаг iter
, но при z
, где не было шага sortBy
, каждое значение передавало всечерез конвейер преобразования по одному, и только после того, как каждое значение было полностью обработано, следующее значение начало обрабатываться).