let aBunch = 1000 let offset = 0 let getIt offset = MyIEnumerable |> Seq.skip aBunch * offset |> Seq.take aBunch |> Seq.iter ( .. some processing ...) Calling getIt() with different offsets eventually gives me an 'Invalid operation' exception with additional info that 'the input sequence had insufficient elements' I try to understand why, as both the Seq.Skip and Seq.take do not generate an exception according to the online documentation FSharp CollectionsVersion: (Visual Studio 2010) Beta 1
5 Réponses :
SEQ.SKIP et SEQ.take lancera cette exception si elle s'appelle une valeur supérieure à la séquence. Vous pouvez vérifier le code source dans seq.fs pour voir pourquoi:
let skip count (sequence: seq<_>) = { use e = sequence.GetEnumerator() let latest = ref (Unchecked.defaultof<_>) let ok = ref false for i in 1 .. count do if not (e.MoveNext()) then raise <| System.InvalidOperationException "the input sequence had insufficient elements" while e.MoveNext() do yield e.Current } let take count (sequence : seq<'T>) = if count < 0 then invalidArg "count" "the number of elements to take may not be negative" (* Note: don't create or dispose any IEnumerable if n = 0 *) if count = 0 then empty else { use e = sequence.GetEnumerator() for i in 0 .. count - 1 do if not (e.MoveNext()) then raise <| System.InvalidOperationException "the input sequence had insufficient elements" yield e.Current }
Je sais que c'est une vieille question, mais au cas où quelqu'un vient à travers cela dans une recherche de la façon dont je l'ai fait: p>
Vous pouvez utiliser Seq.trunate si Vous voulez au plus n em> articles. Il ne lancera pas une exception si moins que les articles n em> sont disponibles. P>
Ceci s'applique uniquement à la partie code> seq.take code> de la question, pas seq.skip code>, je suppose?
pour un combiné avec EXCEPTER code> Vous pouvez ajouter votre propre version au module SEQ, comme ceci:
seq.trunate code> (qui est un équivalent d'équivalent
SEQ.take de code> - il prendra autant d'articles disponibles sans lancer une exception). P>
[1..10]
|> Seq.skipSafe 20
|> Seq.truncate 5
(* returns empty seq *)
Voici une implémentation de "Skipsafe" légèrement plus courte à l'aide de fonctions intégrées:
|> Seq.zip (Seq.initInfinite id) |> Seq.skipWhile (fun (i, _) -> i < num) |> Seq.map snd
module Seq = let trySkip count source = source |> Seq.indexed |> Seq.filter(fst >> (<=) count) |> Seq.map snd
La documentation ne dit rien des exceptions; Les documents sont incomplets. Je déposerai un bogue DOC.