Chunked Enumerable revisited (in F#)
Revisiting an old post on the subject, prompted by a recent question on the MSDN Visual F# forum.
Despite it being a very common thing to want to do, to process a stream of data in blocks, there isn't a library function for it yet; and it's not something that can be put together in a functional form using the pieces we have in the Collections.Seq module. Either, as in my earlier attempts, we have to go into object-land, with intrusions into the implementation details of enumerations (and their disposal), and eager evaluation at best; or we have to go imperative/procedural to get full lazy evaluation as per the code buried within the this C# example.
For idiomatic F#, we don't want an extension method, but a stand-alone function which we can chain into the usual pipeline of |> operations, so we would translate it thus —
let chunk n (source : seq<'a>) = | |
let makechunk (source : System.Collections.Generic.IEnumerator<'a>) n = | |
seq { yield source.Current | |
let mutable i = 0 | |
while (i < n) && source.MoveNext() do | |
yield source.Current | |
i <- i + 1 | |
} | |
seq { use enumerator = source.GetEnumerator() | |
while enumerator.MoveNext() do | |
yield makechunk enumerator (n-1) | |
};; |
where we bury the imperative/mutable kernel, the place where we count the number of steps we take (or stop early when we hit the end of the input), inside an inner function.