Partager via


Séquences

Une séquence est une série logique d’éléments d’un seul type. Les séquences sont particulièrement utiles lorsque vous disposez d’une collection de données volumineuse et ordonnée, mais n’attendez pas nécessairement à utiliser tous les éléments. Les éléments de séquence individuels sont calculés uniquement en fonction des besoins, de sorte qu’une séquence peut fournir de meilleures performances qu’une liste dans les situations où tous les éléments ne sont pas utilisés. Les séquences sont représentées par le seq<'T> type, qui est un alias pour IEnumerable<T>. Par conséquent, tout type .NET qui implémente IEnumerable<T> l’interface peut être utilisé comme séquence. Le module Seq prend en charge les manipulations impliquant des séquences.

Expressions de séquence

Une expression de séquence est une expression qui prend la valeur d’une séquence. Les expressions de séquence peuvent prendre plusieurs formes. Le formulaire le plus simple spécifie une plage. Par exemple, seq { 1 .. 5 } crée une séquence qui contient cinq éléments, y compris les points de terminaison 1 et 5. Vous pouvez également spécifier un incrément (ou décrémentation) entre deux périodes doubles. Par exemple, le code suivant crée la séquence de multiples de 10.

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

Les expressions de séquence sont constituées d’expressions F# qui produisent des valeurs de la séquence. Vous pouvez également générer des valeurs par programmation :

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

L’exemple précédent utilise l’opérateur -> , qui vous permet de spécifier une expression dont la valeur deviendra une partie de la séquence. Vous ne pouvez utiliser -> que si chaque partie du code qui suit retourne une valeur.

Vous pouvez également spécifier le do mot clé, avec une option facultative yield qui suit :

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
}

Le code suivant génère une liste de paires de coordonnées ainsi qu’un index dans un tableau qui représente la grille. Notez que la première for expression nécessite une do spécification.

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

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

Une if expression utilisée dans une séquence est un filtre. Par exemple, pour générer une séquence de nombres premiers uniquement, en supposant que vous avez une fonction isprime de type int -> bool, construisez la séquence comme suit.

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

Comme mentionné précédemment, do il est nécessaire ici parce qu’il n’y a aucune else branche qui va avec le if. Si vous essayez d’utiliser ->, vous obtenez une erreur indiquant que toutes les branches ne retournent pas une valeur.

Mot clé yield!

Parfois, vous pouvez inclure une séquence d’éléments dans une autre séquence. Pour inclure une séquence dans une autre séquence, vous devez utiliser le yield! mot clé :

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

Une autre façon de yield! penser est qu’elle aplatit une séquence interne, puis inclut cela dans la séquence contenante.

Lorsqu’elle yield! est utilisée dans une expression, toutes les autres valeurs uniques doivent utiliser le yield mot clé :

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

L’exemple précédent génère la valeur en plus de x toutes les valeurs de 1 à x chaque x.

Exemples

Le premier exemple utilise une expression de séquence qui contient une itération, un filtre et un rendement pour générer un tableau. Ce code imprime une séquence de nombres premiers compris entre 1 et 100 dans la console.

// 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

L’exemple suivant crée une table de multiplication composée de tuples de trois éléments, chacune composée de deux facteurs et du produit :

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

L’exemple suivant illustre l’utilisation de yield! combiner des séquences individuelles en une seule séquence finale. Dans ce cas, les séquences de chaque sous-arborescence d’une arborescence binaire sont concaténées dans une fonction récursive pour produire la séquence finale.

// 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

Utilisation de séquences

Les séquences prennent en charge la plupart des mêmes fonctions que les listes. Les séquences prennent également en charge les opérations telles que le regroupement et le comptage à l’aide de fonctions de génération de clés. Les séquences prennent également en charge des fonctions plus diversifiées pour extraire des sous-séquences.

De nombreux types de données, tels que les listes, les tableaux, les jeux et les mappages, sont implicitement des séquences, car elles sont des collections énumérables. Une fonction qui prend une séquence en tant qu’argument fonctionne avec l’un des types de données F# courants, en plus de tout type de données .NET qui implémente System.Collections.Generic.IEnumerable<'T>. Contrairement à une fonction qui prend une liste en tant qu’argument, qui ne peut prendre que des listes. Le type seq<'T> est une abréviation de type pour IEnumerable<'T>. Cela signifie que tout type qui implémente le générique System.Collections.Generic.IEnumerable<'T>, qui inclut des tableaux, des listes, des ensembles et des mappages en F#, ainsi que la plupart des types de collection .NET, est compatible avec le seq type et peut être utilisé partout où une séquence est attendue.

Fonctions de module

Le module Seq dans l’espace de noms FSharp.Collections contient des fonctions permettant d’utiliser des séquences. Ces fonctions fonctionnent également avec des listes, des tableaux, des cartes et des ensembles, car tous ces types sont énumérables et peuvent donc être traités comme des séquences.

Création de séquences

Vous pouvez créer des séquences à l’aide d’expressions de séquence, comme décrit précédemment ou à l’aide de certaines fonctions.

Vous pouvez créer une séquence vide à l’aide de Seq.empty, ou vous pouvez créer une séquence d’un seul élément spécifié à l’aide de Seq.singleton.

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

Vous pouvez utiliser Seq.init pour créer une séquence pour laquelle les éléments sont créés à l’aide d’une fonction que vous fournissez. Vous fournissez également une taille pour la séquence. Cette fonction est tout comme List.init, sauf que les éléments ne sont pas créés tant que vous n’avez pas itéré dans la séquence. Le code suivant illustre l’utilisation de Seq.init.

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

La sortie est

0 10 20 30 40

En utilisant Seq.ofArray et Seq.ofList’T<> Function, vous pouvez créer des séquences à partir de tableaux et de listes. Toutefois, vous pouvez également convertir des tableaux et des listes en séquences à l’aide d’un opérateur de cast. Les deux techniques sont présentées dans le code suivant.

// 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

En utilisant Seq.cast, vous pouvez créer une séquence à partir d’une collection faiblement typée, telle que celles définies dans System.Collections. Ces collections faiblement typées ont le type System.Object d’élément et sont énumérées à l’aide du type non générique System.Collections.Generic.IEnumerable&#96;1 . Le code suivant illustre l’utilisation de Seq.cast la conversion d’une System.Collections.ArrayList séquence en séquence.

open System

let arr = ResizeArray<int>(10)

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

let seqCast = Seq.cast arr

Vous pouvez définir des séquences infinies à l’aide de la fonction Seq.initInfinite . Pour une telle séquence, vous fournissez une fonction qui génère chaque élément à partir de l’index de l’élément. Les séquences infinies sont possibles en raison d’une évaluation différée ; les éléments sont créés en fonction des besoins en appelant la fonction que vous spécifiez. L’exemple de code suivant produit une séquence infinie de nombres à virgule flottante, dans ce cas la série alternée de réciproques de carrés d’entiers successifs.

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 génère une séquence à partir d’une fonction de calcul qui prend un état et la transforme pour produire chaque élément suivant dans la séquence. L’état est simplement une valeur utilisée pour calculer chaque élément et peut changer à mesure que chaque élément est calculé. Le deuxième argument à Seq.unfold est la valeur initiale utilisée pour démarrer la séquence. Seq.unfold utilise un type d’option pour l’état, qui vous permet d’arrêter la séquence en retournant la None valeur. Le code suivant montre deux exemples de séquences et seq1fib, qui sont générées par une unfold opération. Le premier, seq1est juste une séquence simple avec des nombres jusqu’à 20. Le deuxième, fibutilise unfold pour calculer la séquence Fibonacci. Étant donné que chaque élément de la séquence Fibonacci est la somme des deux nombres Fibonacci précédents, la valeur d’état est un tuple qui se compose des deux nombres précédents dans la séquence. La valeur initiale est (0,1), les deux premiers nombres de la séquence.

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

La sortie est la suivante :

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 

Le code suivant est un exemple qui utilise la plupart des fonctions de module de séquence décrites ici pour générer et calculer les valeurs des séquences infinies. L’exécution du code peut prendre quelques minutes.

// 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 =
    sequence
    |> Seq.skip 1                      // skip first item (matching the original behavior)
    |> Seq.truncate length             // don't take more than length items
    |> Seq.scan (+) 0.0                // generate running sums
    |> Seq.skip 1                      // skip the initial 0.0 from sequence of running sums

// 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)

Recherche et recherche d’éléments

Les séquences prennent en charge les fonctionnalités disponibles avec des listes : Seq.exists, Seq.exists2, Seq.find, Seq.findIndex, Seq.pick, Seq.tryFind et Seq.tryFindIndex. Les versions de ces fonctions disponibles pour les séquences évaluent la séquence uniquement jusqu’à l’élément recherché. Pour obtenir des exemples, consultez Listes.

Obtention de sous-séquences

Seq.filter et Seq.choose sont similaires aux fonctions correspondantes disponibles pour les listes, sauf que le filtrage et le choix ne se produisent pas tant que les éléments de séquence ne sont pas évalués.

Seq.truncate crée une séquence à partir d’une autre séquence, mais limite la séquence à un nombre spécifié d’éléments. Seq.take crée une séquence qui contient uniquement un nombre spécifié d’éléments à partir du début d’une séquence. S’il y a moins d’éléments dans la séquence que vous spécifiez à prendre, Seq.take lève un System.InvalidOperationException. La différence entre Seq.take et Seq.truncate qui Seq.truncate n’entraîne pas d’erreur si le nombre d’éléments est inférieur au nombre que vous spécifiez.

Le code suivant montre le comportement et les différences entre Seq.truncate et 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

La sortie, avant que l’erreur ne se produise, est la suivante.

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

À l’aide de Seq.takeWhile, vous pouvez spécifier une fonction de prédicat (fonction booléenne) et créer une séquence à partir d’une autre séquence composée de ces éléments de la séquence d’origine pour lesquelles le prédicat est true, mais s’arrêter avant le premier élément pour lequel le prédicat retourne false. Seq.skip retourne une séquence qui ignore un nombre spécifié des premiers éléments d’une autre séquence et retourne les éléments restants. Seq.skipWhile retourne une séquence qui ignore les premiers éléments d’une autre séquence tant que le prédicat retourne true, puis retourne les éléments restants, en commençant par le premier élément pour lequel le prédicat retourne false.

L’exemple de code suivant illustre le comportement et les différences entre Seq.takeWhile, Seq.skipet 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

La sortie est la suivante.

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

Transformation de séquences

Seq.pairwise crée une nouvelle séquence dans laquelle les éléments successifs de la séquence d’entrée sont regroupés en tuples.

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 est semblable Seq.pairwise, sauf qu’au lieu de produire une séquence de tuples, elle produit une séquence de tableaux qui contiennent des copies d’éléments adjacents (une fenêtre) à partir de la séquence. Vous spécifiez le nombre d’éléments adjacents souhaités dans chaque tableau.

L’exemple de code suivant illustre l’utilisation de Seq.windowed. Dans ce cas, le nombre d’éléments dans la fenêtre est 3. L’exemple utilise printSeq, qui est défini dans l’exemple de code précédent.

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

La sortie est la suivante.

Séquence initiale :

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

Opérations avec plusieurs séquences

Seq.zip et Seq.zip3 prennent deux ou trois séquences et produisent une séquence de tuples. Ces fonctions sont similaires aux fonctions correspondantes disponibles pour les listes. Il n’existe aucune fonctionnalité correspondante pour séparer une séquence en deux séquences ou plus. Si vous avez besoin de cette fonctionnalité pour une séquence, convertissez la séquence en liste et utilisez List.unzip.

Tri, comparaison et regroupement

Les fonctions de tri prises en charge pour les listes fonctionnent également avec des séquences. Cela inclut Seq.sort et Seq.sortBy. Ces fonctions effectuent une itération dans l’ensemble de la séquence.

Vous comparez deux séquences à l’aide de la fonction Seq.compareWith . La fonction compare les éléments successifs à son tour et s’arrête lorsqu’elle rencontre la première paire inégale. Tous les éléments supplémentaires ne contribuent pas à la comparaison.

Le code suivant montre l’utilisation de 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.")

Dans le code précédent, seul le premier élément est calculé et examiné, et le résultat est -1.

Seq.countBy prend une fonction qui génère une valeur appelée clé pour chaque élément. Une clé est générée pour chaque élément en appelant cette fonction sur chaque élément. Seq.countBy retourne ensuite une séquence qui contient les valeurs de clé et un nombre d’éléments qui ont généré chaque valeur de la clé.

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

La sortie est la suivante.

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

La sortie précédente indique qu’il y avait 34 éléments de la séquence d’origine qui ont produit la clé 1, 33 valeurs qui ont produit la clé 2 et 33 valeurs qui ont produit la clé 0.

Vous pouvez regrouper des éléments d’une séquence en appelant Seq.groupBy. Seq.groupBy prend une séquence et une fonction qui génère une clé à partir d’un élément. La fonction est exécutée sur chaque élément de la séquence. Seq.groupBy retourne une séquence de tuples, où le premier élément de chaque tuple est la clé et le second est une séquence d’éléments qui produisent cette clé.

L’exemple de code suivant montre comment Seq.groupBy partitionner la séquence de nombres compris entre 1 et 100 dans trois groupes qui ont les valeurs de clé distinctes 0, 1 et 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

La sortie est la suivante.

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

Vous pouvez créer une séquence qui élimine les éléments dupliqués en appelant Seq.distinct. Vous pouvez également utiliser Seq.distinctBy, qui prend une fonction de génération de clé pour être appelée sur chaque élément. La séquence résultante contient des éléments de la séquence d’origine qui ont des clés uniques ; les éléments ultérieurs qui produisent une clé en double à un élément antérieur sont ignorés.

L’exemple de code suivant illustre l’utilisation de Seq.distinct. Seq.distinct est démontré en générant des séquences qui représentent des nombres binaires, puis montrant que les seuls éléments distincts sont 0 et 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

Le code suivant montre Seq.distinctBy en commençant par une séquence qui contient des nombres négatifs et positifs et en utilisant la fonction valeur absolue comme fonction de génération de clé. La séquence résultante manque tous les nombres positifs qui correspondent aux nombres négatifs de la séquence, car les nombres négatifs apparaissent plus haut dans la séquence et sont donc sélectionnés au lieu des nombres positifs qui ont la même valeur absolue, ou clé.

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

Séquences en lecture seule et mises en cache

Seq.readonly crée une copie en lecture seule d’une séquence. Seq.readonly est utile lorsque vous disposez d’une collection en lecture-écriture, telle qu’un tableau, et que vous ne souhaitez pas modifier la collection d’origine. Cette fonction peut être utilisée pour conserver l’encapsulation des données. Dans l’exemple de code suivant, un type qui contient un tableau est créé. Une propriété expose le tableau, mais au lieu de retourner un tableau, elle retourne une séquence créée à partir du tableau à l’aide Seq.readonlyde .

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 crée une version stockée d’une séquence. Permet Seq.cache d’éviter la réévaluation d’une séquence ou lorsque vous avez plusieurs threads qui utilisent une séquence, mais vous devez vous assurer que chaque élément n’est agi qu’une seule fois. Lorsque vous disposez d’une séquence utilisée par plusieurs threads, vous pouvez avoir un thread qui énumère et calcule les valeurs de la séquence d’origine, et les threads restants peuvent utiliser la séquence mise en cache.

Exécution de calculs sur des séquences

Les opérations arithmétiques simples sont similaires à celles des listes, telles que Seq.average, Seq.sum, Seq.averageBy, Seq.sumBy, etc.

Seq.fold, Seq.reduce et Seq.scan sont similaires aux fonctions correspondantes disponibles pour les listes. Les séquences prennent en charge un sous-ensemble des variantes complètes de ces fonctions qui répertorient la prise en charge. Pour plus d’informations et d’exemples, consultez Listes.

Voir aussi