tags:

views:

289

answers:

2
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

+5  A: 

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 }
Dustin Campbell
+2  A: 

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.

Joel Mueller