F# has a handy method called Unfold. Think of it as the logical opposite of an Aggregate function. Aggregates take a sequence of elements and convert them to a single element. An unfold method will take a single element and turn it into a (potentially infinite) sequence of elements.
The API is straight forward. It takes two parameters
This is a very powerful function which allows you to quickly build all sorts of interesting functions. Lets look at a potential implementation of Enumerable.Range as an unfold expression.
public static IEnumerable<int> Range(int start, int count) { return Enumerable.Unfold( start, x => x - start < count ? Option.Create(Tuple.Create(x, x + 1)) : Option.Empty); }
Not as efficient as the framework version of Range but a good mental exercise to get your head around using Unfold. Implementing this method in C# is fairly straight forward.
public static IEnumerable<TResult> Unfold<TSource, TResult>( TSource state, Func<TSource, Option<Tuple<TResult, TSource>>> func) { if (func == null) { throw new ArgumentNullException("func"); } return UnfoldHelper(state, func); } private static IEnumerable<TResult> UnfoldHelper<TSource, TResult>( TSource state, Func<TSource, Option<Tuple<TResult, TSource>>> func) { do { var result = func(state); if (!result.HasValue) { break; } yield return result.Value.First; state = result.Value.Second; } while (true); }