F#
Sekwencje przepływów pracy
Szukaj…
wydajność i wydajność!
W przepływach pracy z sekwencją yield
dodaje jeden element do budowanej sekwencji. (W terminologii monadycznej jest to 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!
(wymawiane huk wydajności ) wstawia wszystkie elementy innej sekwencji do budowanej sekwencji. Lub innymi słowy, dodaje sekwencję. (W odniesieniu do monad jest 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']
Sekwencje utworzone przez przepływy pracy sekwencji są również leniwe, co oznacza, że elementy sekwencji nie są tak naprawdę oceniane, dopóki nie są potrzebne. Kilka sposobów wymuszenia pozycji to wywołanie Seq.take
(ciągnie pierwsze n elementów do sekwencji), Seq.iter
(stosuje funkcję do każdego elementu do wykonywania efektów ubocznych) lub Seq.toList
(konwertuje sekwencję na listę) . Połączenie tego z rekurencją to miejsce, w którym yield!
naprawdę zaczyna świecić.
> 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]
dla
for
sekwencji wyrażenie ma wyglądać podobnie jak jego bardziej znanego kuzyna, imperatyw dla pętli. „Zapętla” sekwencję i ocenia treść każdej iteracji w sekwencji, którą generuje. Podobnie jak wszystko związane z sekwencją, NIE jest ona zmienna.
> 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]