Vale lembrar que a preguiça que vem junto com o tipo de dados Seq <‘a> do F # (o equivalente IEnumerable <T>) tem vantagens além de apenas criar sequências infinitas.
Ao usar Seq, todas as transformações que você faz a sequência são sequenciais, de modo que ocorrem sequencialmente para cada elemento, em vez de processar todos os elementos antes de passar para a próxima etapa no pipeline de processamento.
Exemplo:
vamos pegar um filtro numérico simples, que permitirá apenas números divisíveis por 2:
let filter1 i = i % 2 = 0
E então temos outra etapa no processo, vamos fazer a mesma coisa para números divisíveis por 3:
let filter2 i = i % 3 = 0
Agora, se você os encadear usando List.filter da seguinte forma:
[1 .. 20] |> List.filter filter1 |> List.filter filter2
O que acontece nos bastidores é que para cada número na lista (1 a 20) o filtro 1 é executado, a lista resultante é alimentada para o filtro 2, então o processo é algo como
1 % 2 = 0
2 % 2 = 0
3 % 2 = 0
4 % 2 = 0
...
20 % 2 = 0
Seguido por
2 % 3 = 0
4 % 3 = 0
6 % 3 = 0
8 % 3 = 0
...
20 % 3 = 0
Produzindo uma lista final de [6; 12; 18]
Agora, se a mesma coisa for feita com um Seq (e a função Seq.filter) assim:
{1 .. 20} |> Seq.filter filter1 |> Seq.filter filter2
Você obtém o seguinte:
1 % 2 = 0
2 % 2 = 0
2 % 3 = 0
3 % 2 = 0
4 % 2 = 0
4 % 3 = 0
...
Isso também funciona se sua fonte for uma Lista e você usar as funções Seq como:
[1 .. 20] |> Seq.filter filtro1 |> Seq.filtro filtro2
Além disso, a mesma coisa acontece em C # quando você usa IEnumerables e iteradores