F#
Workflows de séquence
Recherche…
rendement et rendement!
Dans les flux de travail séquentiels, le yield
ajoute un seul élément dans la séquence en cours de création. (Dans la terminologie monadique, c'est le return
.)
> seq { yield 1; yield 2; yield 3 }
val it: seq<int> = seq [1; 2; 3]
> let homogenousTup2ToSeq (a, b) = seq { yield a; yield b }
> tup2Seq ("foo", "bar")
val homogenousTup2ToSeq: 'a * 'a -> seq<'a>
val it: seq<string> = seq ["foo"; "bar"]
yield!
(prononcé bang de rendement ) insère tous les éléments d'une autre séquence dans cette séquence en cours de construction. Ou, en d'autres termes, il ajoute une séquence. (En ce qui concerne monades, on bind
).
> seq { yield 1; yield! [10;11;12]; yield 20 }
val it: seq<int> = seq [1; 10; 11; 12; 20]
// Creates a sequence containing the items of seq1 and seq2 in order
> let concat seq1 seq2 = seq { yield! seq1; yield! seq2 }
> concat ['a'..'c'] ['x'..'z']
val concat: seq<'a> -> seq<'a> -> seq<'a>
val it: seq<int> = seq ['a'; 'b'; 'c'; 'x'; 'y'; 'z']
Les séquences créées par les flux de travail de séquence sont également paresseuses, ce qui signifie que les éléments de la séquence ne sont pas réellement évalués tant qu'ils ne sont pas nécessaires. Quelques méthodes pour forcer les éléments incluent l'appel Seq.take
(extrait les n premiers éléments dans une séquence), Seq.iter
(applique une fonction à chaque élément pour exécuter les effets secondaires) ou Seq.toList
(convertit une séquence en liste) . Combiner cela avec la récursivité est là où le yield!
commence vraiment à briller.
> let rec numbersFrom n = seq { yield n; yield! numbersFrom (n + 1) }
> let naturals = numbersFrom 0
val numbersFrom: int -> seq<int>
val naturals: seq<int> = seq [0; 1; 2; ...]
// Just like Seq.map: applies a mapping function to each item in a sequence to build a new sequence
> let rec map f seq1 =
if Seq.isEmpty seq1 then Seq.empty
else seq { yield f (Seq.head seq1); yield! map f (Seq.tail seq1) }
> map (fun x -> x * x) [1..10]
val map: ('a -> 'b) -> seq<'a> -> 'b
val it: seq<int> = seq [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]
pour
for
séquence, l'expression est conçue pour ressembler à son cousin le plus célèbre, l'impératif for-loop. Il "boucle" à travers une séquence et évalue le corps de chaque itération dans la séquence qu'il génère. Tout comme toute séquence liée, elle n'est PAS mutable.
> let oneToTen = seq { for x in 1..10 -> x }
val oneToTen: seq<int> = seq [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
// Or, equivalently:
> let oneToTen = seq { for x in 1..10 do yield x }
val oneToTen: seq<int> = seq [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
// Just like Seq.map: applies a mapping function to each item in a sequence to build a new sequence
> let map mapping seq1 = seq { for x in seq1 do yield mapping x }
> map (fun x -> x * x) [1..10]
val map: ('a -> 'b) -> seq<'a> -> seq<'b>
val it: seq<int> = seq [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]
// An infinite sequence of consecutive integers starting at 0
> let naturals =
let numbersFrom n = seq { yield n; yield! numbersFrom (n + 1) }
numbersFrom 0
// Just like Seq.filter: returns a sequence consisting only of items from the input sequence that satisfy the predicate
> let filter predicate seq1 = seq { for x in seq1 do if predicate x then yield x }
> let evenNaturals = naturals |> filter (fun x -> x % 2 = 0)
val naturals: seq<int> = seq [1; 2; 3; ...]
val filter: ('a -> bool) -> seq<'a> -> seq<'a>
val evenNaturals: seq<int> = seq [2; 4; 6; ...]
// Just like Seq.concat: concatenates a collection of sequences together
> let concat seqSeq = seq { for seq in seqSeq do yield! seq }
> concat [[1;2;3];[10;20;30]]
val concat: seq<#seq<'b>> -> seq<'b>
val it: seq<int> = seq [1; 2; 3; 10; 20; 30]