Sekvence

Sekvence je logická řada prvků všech typů. Sekvence jsou užitečné zejména v případě, že máte velkou seřazenou kolekci dat, ale neočekáváte, že budete používat všechny prvky. Jednotlivé prvky sekvence se počítají jenom podle potřeby, takže sekvence může poskytovat lepší výkon než seznam v situacích, kdy se nepoužívají všechny prvky. Sekvence jsou reprezentovány typem seq<'T> , což je alias pro IEnumerable<T>. Proto lze jakýkoli typ .NET, který implementuje IEnumerable<T> rozhraní, použít jako posloupnost. Modul Seq poskytuje podporu pro manipulaci s sekvencemi.

Sekvenční výrazy

Sekvenční výraz je výraz, který se vyhodnotí jako sekvence. Sekvenční výrazy mohou mít řadu forem. Nejjednodušší formulář určuje rozsah. seq { 1 .. 5 } Například vytvoří sekvenci, která obsahuje pět prvků včetně koncových bodů 1 a 5. Můžete také zadat přírůstek (nebo dekrement) mezi dvěma dvojitými tečkami. Například následující kód vytvoří sekvenci násobků 10.

// Sequence that has an increment.
seq { 0..10..100 }

Sekvenční výrazy se skládají z výrazů jazyka F#, které vytvářejí hodnoty sekvence. Hodnoty můžete generovat také prostřednictvím kódu programu:

seq { for i in 1..10 -> i * i }

Předchozí ukázka používá -> operátor, který umožňuje zadat výraz, jehož hodnota se stane součástí sekvence. Můžete použít -> pouze v případě, že každá část kódu, která následuje, vrátí hodnotu.

Případně můžete zadat do klíčové slovo s volitelným yield kódem, který následuje:

seq {
    for i in 1..10 do
        yield i * i
}

// The 'yield' is implicit and doesn't need to be specified in most cases.
seq {
    for i in 1..10 do
        i * i
}

Následující kód vygeneruje seznam párů souřadnic spolu s indexem do pole, které představuje mřížku. Všimněte si, že první for výraz vyžaduje do zadání.

let (height, width) = (10, 10)

seq {
    for row in 0 .. width - 1 do
        for col in 0 .. height - 1 -> (row, col, row * width + col)
}

Výraz if použitý v sekvenci je filtr. Pokud chcete například vygenerovat sekvenci pouze primárních čísel za předpokladu, že máte funkci isprime typu int -> bool, sestavte sekvenci následujícím způsobem.

seq {
    for n in 1..100 do
        if isprime n then
            n
}

Jak jsme zmínili dříve, je zde požadován, do protože neexistuje žádná else větev, která jde s if. Pokud se pokusíte použít ->, zobrazí se chyba oznamující, že ne všechny větve vracejí hodnotu.

Klíčové slovo yield!

Někdy můžete chtít zahrnout posloupnost prvků do jiné sekvence. Pokud chcete zahrnout sekvenci do jiné sekvence, budete muset použít yield! klíčové slovo:

// Repeats '1 2 3 4 5' ten times
seq {
    for _ in 1..10 do
        yield! seq { 1; 2; 3; 4; 5}
}

Dalším způsobem myšlení yield! je, že zploštěná vnitřní sekvenci a pak zahrnuje, že v obsahující sekvenci.

Při yield! použití ve výrazu musí všechny ostatní jednotlivé hodnoty používat yield klíčové slovo:

// Combine repeated values with their values
seq {
    for x in 1..10 do
        yield x
        yield! seq { for i in 1..x -> i}
}

Předchozí příklad vytvoří hodnotu x kromě všech hodnot od 1 do x každého z nich x.

Příklady

První příklad používá sekvenční výraz, který obsahuje iteraci, filtr a výnos k vygenerování pole. Tento kód vypíše posloupnost prime čísel mezi 1 a 100 na konzolu.

// Recursive isprime function.
let isprime n =
    let rec check i =
        i > n / 2 || (n % i <> 0 && check (i + 1))

    check 2

let aSequence =
    seq {
        for n in 1..100 do
            if isprime n then
                n
    }

for x in aSequence do
    printfn "%d" x

Následující příklad vytvoří tabulku násobení, která se skládá z řazených kolekcí členů ze tří prvků, z nichž každý se skládá ze dvou faktorů a součinu:

let multiplicationTable =
    seq {
        for i in 1..9 do
            for j in 1..9 -> (i, j, i * j)
    }

Následující příklad ukazuje použití yield! ke kombinování jednotlivých sekvencí do jedné konečné sekvence. V tomto případě jsou sekvence pro každý podstrom v binárním stromu zřetězeny v rekurzivní funkci, aby vznikla konečná sekvence.

// Yield the values of a binary tree in a sequence.
type Tree<'a> =
    | Tree of 'a * Tree<'a> * Tree<'a>
    | Leaf of 'a

// inorder : Tree<'a> -> seq<'a>
let rec inorder tree =
    seq {
        match tree with
        | Tree(x, left, right) ->
            yield! inorder left
            yield x
            yield! inorder right
        | Leaf x -> yield x
    }

let mytree = Tree(6, Tree(2, Leaf(1), Leaf(3)), Leaf(9))
let seq1 = inorder mytree
printfn "%A" seq1

Použití sekvencí

Sekvence podporují mnoho stejných funkcí jako seznamy. Sekvence také podporují operace, jako je seskupování a počítání pomocí funkcí generování klíčů. Sekvence také podporují různorodější funkce pro extrakci dílčích sekvencí.

Mnoho datových typů, jako jsou seznamy, pole, sady a mapy, jsou implicitně sekvence, protože jsou výčty kolekcí. Funkce, která přebírá sekvenci jako argument, funguje s libovolným běžnými datovými typy jazyka F# kromě jakéhokoli datového typu .NET, který implementuje System.Collections.Generic.IEnumerable<'T>. Porovnejte ji s funkcí, která přebírá seznam jako argument, který může obsahovat pouze seznamy. seq<'T> Typ je zkratka typu pro IEnumerable<'T>. To znamená, že jakýkoli typ, který implementuje obecný System.Collections.Generic.IEnumerable<'T>typ , který zahrnuje pole, seznamy, sady a mapy v jazyce F# a také většinu typů kolekcí .NET, je kompatibilní s typem seq a dá se použít všude, kde se očekává posloupnost.

Funkce modulů

Modul Seq v oboru názvů FSharp.Collections obsahuje funkce pro práci se sekvencemi. Tyto funkce fungují i se seznamy, poli, mapami a sadami, protože všechny tyto typy jsou výčtové, a proto se dají považovat za sekvence.

Vytváření sekvencí

Sekvence můžete vytvářet pomocí sekvenčních výrazů, jak je popsáno dříve, nebo pomocí určitých funkcí.

Prázdnou sekvenci můžete vytvořit pomocí seq.empty nebo můžete vytvořit posloupnost pouze jednoho zadaného prvku pomocí Seq.singleton.

let seqEmpty = Seq.empty
let seqOne = Seq.singleton 10

Pomocí seq.init můžete vytvořit posloupnost, pro kterou jsou prvky vytvořeny pomocí funkce, kterou zadáte. Pro sekvenci také zadáte velikost. Tato funkce je stejně jako List.init, s tím rozdílem, že prvky nejsou vytvořeny, dokud nebudete iterovat v posloupnosti. Následující kód ilustruje použití funkce Seq.init.

let seqFirst5MultiplesOf10 = Seq.init 5 (fun n -> n * 10)
Seq.iter (fun elem -> printf "%d " elem) seqFirst5MultiplesOf10

Výstup je

0 10 20 30 40

Pomocí funkce Seq.ofArray a Seq.ofList'T>< můžete vytvářet sekvence z polí a seznamů. Pole a seznamy ale můžete také převést na sekvence pomocí operátoru přetypování. Obě techniky jsou uvedené v následujícím kódu.

// Convert an array to a sequence by using a cast.
let seqFromArray1 = [| 1 .. 10 |] :> seq<int>

// Convert an array to a sequence by using Seq.ofArray.
let seqFromArray2 = [| 1 .. 10 |] |> Seq.ofArray

Pomocí funkce Seq.cast můžete vytvořit sekvenci ze slabě typované kolekce, jako jsou například ty, které jsou definovány v System.Collections. Takové slabě typované kolekce mají typ System.Object elementu a jsou výčty pomocí jiného než obecného System.Collections.Generic.IEnumerable&#96;1 typu. Následující kód znázorňuje použití Seq.cast k převodu na System.Collections.ArrayList sekvenci.

open System

let arr = ResizeArray<int>(10)

for i in 1 .. 10 do
    arr.Add(10)

let seqCast = Seq.cast arr

Nekonečné sekvence můžete definovat pomocí funkce Seq.initInfinite . Pro takovou sekvenci zadáte funkci, která vygeneruje každý prvek z indexu prvku. Nekonečné sekvence jsou možné z důvodu opožděného vyhodnocení; elementy jsou vytvořeny podle potřeby voláním funkce, kterou zadáte. Následující příklad kódu vytvoří nekonečnou sekvenci čísel s plovoucí desetinnou čárkou, v tomto případě střídavou řadu recipročních čtverců po sobě jdoucích celých čísel.

let seqInfinite =
    Seq.initInfinite (fun index ->
        let n = float (index + 1)
        1.0 / (n * n * (if ((index + 1) % 2 = 0) then 1.0 else -1.0)))

printfn "%A" seqInfinite

Seq.unfold vygeneruje sekvenci z výpočetní funkce, která převezme stav a transformuje ji tak, aby vytvořila každý další prvek v sekvenci. Stav je jen hodnota, která se používá k výpočtu jednotlivých prvků a může se měnit při výpočtu každého prvku. Druhým argumentem Seq.unfold je počáteční hodnota, která se používá ke spuštění sekvence. Seq.unfold používá typ možnosti pro stav, který umožňuje ukončit posloupnost vrácením None hodnoty. Následující kód ukazuje dva příklady sekvencí seq1 a fib, které jsou generovány unfold operací. První, seq1je jen jednoduchá posloupnost s čísly až 20. Druhý, fibpoužívá unfold k výpočtu Fibonacci sekvence. Vzhledem k tomu, že každý prvek fibonacciho sekvence je součet předchozích dvou Fibonacciových čísel, je stavová hodnota řazená kolekce členů, která se skládá z předchozích dvou čísel v sekvenci. Počáteční hodnota je (0,1), první dvě čísla v sekvenci.

let seq1 =
    0 // Initial state
    |> Seq.unfold (fun state ->
        if (state > 20) then
            None
        else
            Some(state, state + 1))

printfn "The sequence seq1 contains numbers from 0 to 20."

for x in seq1 do
    printf "%d " x

let fib =
    (0, 1)
    |> Seq.unfold (fun state ->
        let cur, next = state
        if cur < 0 then  // overflow
            None
        else
            let next' = cur + next
            let state' = next, next'
            Some (cur, state') )

printfn "\nThe sequence fib contains Fibonacci numbers."
for x in fib do printf "%d " x

Výstup je následující:

The sequence seq1 contains numbers from 0 to 20.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

The sequence fib contains Fibonacci numbers.

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 

Následující kód je příkladem, který používá mnoho funkcí sekvenčního modulu popsaných zde ke generování a výpočtu hodnot nekonečných sekvencí. Spuštění kódu může trvat několik minut.

// generateInfiniteSequence generates sequences of floating point
// numbers. The sequences generated are computed from the fDenominator
// function, which has the type (int -> float) and computes the
// denominator of each term in the sequence from the index of that
// term. The isAlternating parameter is true if the sequence has
// alternating signs.
let generateInfiniteSequence fDenominator isAlternating =
    if (isAlternating) then
        Seq.initInfinite (fun index ->
            1.0 /(fDenominator index) * (if (index % 2 = 0) then -1.0 else 1.0))
    else
        Seq.initInfinite (fun index -> 1.0 /(fDenominator index))

// The harmonic alternating series is like the harmonic series
// except that it has alternating signs.
let harmonicAlternatingSeries = generateInfiniteSequence (fun index -> float index) true

// This is the series of reciprocals of the odd numbers.
let oddNumberSeries = generateInfiniteSequence (fun index -> float (2 * index - 1)) true

// This is the series of recipocals of the squares.
let squaresSeries = generateInfiniteSequence (fun index -> float (index * index)) false

// This function sums a sequence, up to the specified number of terms.
let sumSeq length sequence =
    (0, 0.0)
    |>
    Seq.unfold (fun state ->
        let subtotal = snd state + Seq.item (fst state + 1) sequence
        if (fst state >= length) then
            None
        else
            Some(subtotal, (fst state + 1, subtotal)))

// This function sums an infinite sequence up to a given value
// for the difference (epsilon) between subsequent terms,
// up to a maximum number of terms, whichever is reached first.
let infiniteSum infiniteSeq epsilon maxIteration =
    infiniteSeq
    |> sumSeq maxIteration
    |> Seq.pairwise
    |> Seq.takeWhile (fun elem -> abs (snd elem - fst elem) > epsilon)
    |> List.ofSeq
    |> List.rev
    |> List.head
    |> snd

// Compute the sums for three sequences that converge, and compare
// the sums to the expected theoretical values.
let result1 = infiniteSum harmonicAlternatingSeries 0.00001 100000
printfn "Result: %f  ln2: %f" result1 (log 2.0)

let pi = Math.PI
let result2 = infiniteSum oddNumberSeries 0.00001 10000
printfn "Result: %f pi/4: %f" result2 (pi/4.0)

// Because this is not an alternating series, a much smaller epsilon
// value and more terms are needed to obtain an accurate result.
let result3 = infiniteSum squaresSeries 0.0000001 1000000
printfn "Result: %f pi*pi/6: %f" result3 (pi*pi/6.0)

Hledání a hledání elementů

Sekvence podporují funkce dostupné v seznamech: Seq.exists, Seq.exists2, Seq.find, Seq.findIndex, Seq.pick, Seq.tryFind a Seq.tryFindIndex. Verze těchto funkcí, které jsou k dispozici pro sekvence, vyhodnocují posloupnost pouze až do prvku, který se hledá. Příklady najdete v tématu Seznamy.

Získávání dílčích sekvencí

Seq.filter a Seq.choose jsou podobné odpovídajícím funkcím, které jsou k dispozici pro seznamy, s tím rozdílem, že filtrování a výběr neprovádí, dokud se nevyhodnotí prvky sekvence.

Seq.truncate vytvoří sekvenci z jiné sekvence, ale omezí sekvenci na zadaný počet prvků. Seq.take vytvoří novou sekvenci, která obsahuje pouze zadaný počet prvků od začátku sekvence. Pokud je v sekvenci méně prvků, než zadáte, Seq.take vyvolá chybu System.InvalidOperationException. Rozdíl mezi Seq.take a Seq.truncate je, že Seq.truncate nevygeneruje chybu, pokud je počet prvků menší než zadané číslo.

Následující kód ukazuje chování a rozdíly mezi Seq.truncate a Seq.take.

let mySeq = seq { for i in 1 .. 10 -> i*i }
let truncatedSeq = Seq.truncate 5 mySeq
let takenSeq = Seq.take 5 mySeq

let truncatedSeq2 = Seq.truncate 20 mySeq
let takenSeq2 = Seq.take 20 mySeq

let printSeq seq1 = Seq.iter (printf "%A ") seq1; printfn ""

// Up to this point, the sequences are not evaluated.
// The following code causes the sequences to be evaluated.
truncatedSeq |> printSeq
truncatedSeq2 |> printSeq
takenSeq |> printSeq
// The following line produces a run-time error (in printSeq):
takenSeq2 |> printSeq

Výstup, před výskytem chyby, je následující.

1 4 9 16 25
1 4 9 16 25 36 49 64 81 100
1 4 9 16 25
1 4 9 16 25 36 49 64 81 100

Pomocí seq.takeWhile můžete zadat predikát funkce (boolean funkce) a vytvořit posloupnost z jiné sekvence tvořené těmito prvky původní sekvence, pro kterou je truepredikát , ale zastavit před prvním prvkem, pro který predikát vrátí false. Funkce Seq.skip vrátí sekvenci, která přeskočí zadaný počet prvních prvků jiné sekvence a vrátí zbývající prvky. Seq.skip While vrátí sekvenci, která přeskočí první prvky jiné sekvence, pokud predikát vrátí true, a poté vrátí zbývající prvky, počínaje prvním prvkem, pro který predikát vrátí false.

Následující příklad kódu ilustruje chování a rozdíly mezi Seq.takeWhile, Seq.skipa Seq.skipWhile.

// takeWhile
let mySeqLessThan10 = Seq.takeWhile (fun elem -> elem < 10) mySeq
mySeqLessThan10 |> printSeq

// skip
let mySeqSkipFirst5 = Seq.skip 5 mySeq
mySeqSkipFirst5 |> printSeq

// skipWhile
let mySeqSkipWhileLessThan10 = Seq.skipWhile (fun elem -> elem < 10) mySeq
mySeqSkipWhileLessThan10 |> printSeq

Výstup je následující.

1 4 9
36 49 64 81 100
16 25 36 49 64 81 100

Transformace sekvencí

Seq.pairwise vytvoří novou sekvenci, ve které se po sobě jdoucí prvky vstupní sekvence seskupí do řazených kolekcí členů.

let printSeq seq1 = Seq.iter (printf "%A ") seq1; printfn ""
let seqPairwise = Seq.pairwise (seq { for i in 1 .. 10 -> i*i })
printSeq seqPairwise

printfn ""
let seqDelta = Seq.map (fun elem -> snd elem - fst elem) seqPairwise
printSeq seqDelta

Seq.windowed je jako Seq.pairwise, s tím rozdílem, že místo vytvoření sekvence řazených kolekcí členů vytvoří posloupnost polí, která obsahují kopie sousedních prvků ( okno) ze sekvence. V každém poli zadáte požadovaný počet sousedních prvků.

Následující příklad kódu ukazuje použití Seq.windowed. V tomto případě je počet prvků v okně 3. Příklad používá printSeq, který je definován v předchozím příkladu kódu.

let seqNumbers = [ 1.0; 1.5; 2.0; 1.5; 1.0; 1.5 ] :> seq<float>
let seqWindows = Seq.windowed 3 seqNumbers
let seqMovingAverage = Seq.map Array.average seqWindows
printfn "Initial sequence: "
printSeq seqNumbers
printfn "\nWindows of length 3: "
printSeq seqWindows
printfn "\nMoving average: "
printSeq seqMovingAverage

Výstup je následující.

Počáteční sekvence:

1.0 1.5 2.0 1.5 1.0 1.5

Windows of length 3:
[|1.0; 1.5; 2.0|] [|1.5; 2.0; 1.5|] [|2.0; 1.5; 1.0|] [|1.5; 1.0; 1.5|]

Moving average:
1.5 1.666666667 1.5 1.333333333

Operace s více sekvencemi

Seq.zip a Seq.zip3 mají dvě nebo tři sekvence a vytvoří sekvenci řazených kolekcí členů. Tyto funkce jsou podobné příslušným funkcím dostupným pro seznamy. Neexistuje žádná odpovídající funkce pro oddělení jedné sekvence do dvou nebo více sekvencí. Pokud tuto funkci potřebujete pro sekvenci, převeďte ji na seznam a použijte List.unzip.

Řazení, porovnávání a seskupování

Funkce řazení podporované pro seznamy také pracují se sekvencemi. To zahrnuje Seq.sort a Seq.sortBy. Tyto funkce iterují celou sekvenci.

Pomocí funkce Seq.compareWith porovnáte dvě sekvence. Funkce porovnává postupně po sobě jdoucí prvky a zastavuje, když narazí na první nerovný pár. Žádné další prvky nepřispívají k porovnání.

Následující kód ukazuje použití Seq.compareWith.

let sequence1 = seq { 1 .. 10 }
let sequence2 = seq { 10 .. -1 .. 1 }

// Compare two sequences element by element.
let compareSequences =
    Seq.compareWith (fun elem1 elem2 ->
        if elem1 > elem2 then 1
        elif elem1 < elem2 then -1
        else 0)

let compareResult1 = compareSequences sequence1 sequence2
match compareResult1 with
| 1 -> printfn "Sequence1 is greater than sequence2."
| -1 -> printfn "Sequence1 is less than sequence2."
| 0 -> printfn "Sequence1 is equal to sequence2."
| _ -> failwith("Invalid comparison result.")

V předchozím kódu se vypočítá a prozkoumá pouze první prvek a výsledek je -1.

Seq.countBy přebírá funkci, která vygeneruje hodnotu nazvanou klíč pro každý prvek. Pro každý prvek se vygeneruje klíč voláním této funkce na každém prvku. Seq.countBy pak vrátí sekvenci obsahující hodnoty klíče a počet prvků, které vygenerovaly každou hodnotu klíče.

let mySeq1 = seq { 1.. 100 }

let printSeq seq1 = Seq.iter (printf "%A ") seq1

let seqResult =
    mySeq1
    |> Seq.countBy (fun elem ->
        if elem % 3 = 0 then 0
        elif elem % 3 = 1 then 1
        else 2)

printSeq seqResult

Výstup je následující.

(1, 34) (2, 33) (0, 33)

Předchozí výstup ukazuje, že v původní sekvenci bylo 34 prvků, které vytvořily klíč 1, 33 hodnot, které vytvořily klíč 2 a 33 hodnot, které vytvořily klíč 0.

Prvky sekvence můžete seskupit voláním Seq.groupBy. Seq.groupBy přebírá sekvenci a funkci, která generuje klíč z elementu. Funkce se spustí na každém prvku sekvence. Seq.groupBy vrátí sekvenci řazených kolekcí členů, kde první prvek každé řazené kolekce členů je klíč a druhý je posloupnost prvků, které tento klíč vytvářejí.

Následující příklad kódu ukazuje použití Seq.groupBy rozdělení posloupnosti čísel od 1 do 100 do tří skupin, které mají jedinečné hodnoty klíče 0, 1 a 2.

let sequence = seq { 1 .. 100 }

let printSeq seq1 = Seq.iter (printf "%A ") seq1

let sequences3 =
    sequences
    |> Seq.groupBy (fun index ->
        if (index % 3 = 0) then 0
        elif (index % 3 = 1) then 1
        else 2)

sequences3 |> printSeq

Výstup je následující.

(1, seq [1; 4; 7; 10; ...]) (2, seq [2; 5; 8; 11; ...]) (0, seq [3; 6; 9; 12; ...])

Můžete vytvořit sekvenci, která eliminuje duplicitní prvky voláním Seq.distinct. Nebo můžete použít Seq.distinctBy, která přebírá funkci generování klíčů, která má být volána pro každý prvek. Výsledná sekvence obsahuje prvky původní sekvence, které mají jedinečné klíče; pozdější prvky, které vytvoří duplicitní klíč k dřívějšímu prvku, se zahodí.

Následující příklad kódu ilustruje použití Seq.distinct. Seq.distinct je demonstrována generováním sekvencí, které představují binární čísla, a pak ukazují, že jediné jedinečné prvky jsou 0 a 1.

let binary n =
    let rec generateBinary n =
        if (n / 2 = 0) then [n]
        else (n % 2) :: generateBinary (n / 2)

    generateBinary n
    |> List.rev
    |> Seq.ofList

printfn "%A" (binary 1024)

let resultSequence = Seq.distinct (binary 1024)
printfn "%A" resultSequence

Následující kód ukazuje Seq.distinctBy , že začíná sekvencí, která obsahuje záporná a kladná čísla a používá funkci absolutní hodnoty jako funkci generující klíč. Výsledné sekvenci chybí všechna kladná čísla, která odpovídají záporným číslům v sekvenci, protože záporná čísla se zobrazují dříve v posloupnosti, a proto jsou vybrána místo kladných čísel se stejnou absolutní hodnotou nebo klíčem.

let inputSequence = { -5 .. 10 }
let printSeq seq1 = Seq.iter (printf "%A ") seq1

printfn "Original sequence: "
printSeq inputSequence

printfn "\nSequence with distinct absolute values: "
let seqDistinctAbsoluteValue = Seq.distinctBy (fun elem -> abs elem) inputSequence
printSeq seqDistinctAbsoluteValue

Sekvence jen pro čtení a mezipaměť

Seq.readonly vytvoří kopii sekvence jen pro čtení. Seq.readonly je užitečná, pokud máte kolekci pro čtení i zápis, například pole, a nechcete upravovat původní kolekci. Tuto funkci lze použít k zachování zapouzdření dat. V následujícím příkladu kódu je vytvořen typ, který obsahuje pole. Vlastnost zpřístupňuje pole, ale místo vrácení pole vrátí sekvenci, která je vytvořena z pole pomocí .Seq.readonly

type ArrayContainer(start, finish) =
    let internalArray = [| start .. finish |]
    member this.RangeSeq = Seq.readonly internalArray
    member this.RangeArray = internalArray

let newArray = new ArrayContainer(1, 10)
let rangeSeq = newArray.RangeSeq
let rangeArray = newArray.RangeArray

// These lines produce an error:
//let myArray = rangeSeq :> int array
//myArray[0] <- 0

// The following line does not produce an error.
// It does not preserve encapsulation.
rangeArray[0] <- 0

Seq.cache vytvoří uloženou verzi sekvence. Slouží Seq.cache k tomu, aby se zabránilo opětovnému hodnocení sekvence, nebo pokud máte více vláken, které používají posloupnost, ale musíte zajistit, aby každý prvek fungoval pouze jednou. Pokud máte posloupnost, kterou používá více vláken, můžete mít jedno vlákno, které vytvoří výčet a vypočítá hodnoty pro původní sekvenci a zbývající vlákna můžou použít sekvenci uloženou v mezipaměti.

Provádění výpočtů v sekvencích

Jednoduché aritmetické operace jsou podobné seznamům, například Seq.average, Seq.sum, Seq.averageBy, Seq.sumBy atd.

Seq.fold, Seq.reduce a Seq.scan jsou podobné odpovídajícím funkcím, které jsou k dispozici pro seznamy. Sekvence podporují podmnožinu úplných variant těchto funkcí, které uvádějí podporu. Další informace a příklady najdete v tématu Seznamy.

Viz také