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 Collections
Version: (Visual Studio 2010) Beta 1
I know this is an old question, but in case someone comes across this in a search the way I did:
You can use Seq.truncate if you want at most n items. It won't throw an exception if fewer than n items are available.
Both Seq.skip and Seq.take will throw this exception if called with a value larger than the sequence. You can check the source code in Seq.fs to see why:
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 }
For an exceptionless skip
you can add your own version to the Seq module like this:
module Seq =
let skipSafe (num: int) (source: seq<'a>) : seq<'a> =
seq {
use e = source.GetEnumerator()
let idx = ref 0
let loop = ref true
while !idx < num && !loop do
if not(e.MoveNext()) then
loop := false
idx := !idx + 1
while e.MoveNext() do
yield e.Current
}
Combined with Seq.truncate
(which is an exceptionless Seq.take
equivalent - it will take as much items are available without throwing an exception).
[1..10]
|> Seq.skipSafe 20
|> Seq.truncate 5
(* returns empty seq *)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With