Add the Nuget Package to your project
It is an abstraction built on top of IEnumerable
to lazily (and maybe even asynchronously) generate sequences with low friction.
Because I had an idea and thought it would be fun to make it
Inspired by lazy evaluation in functional languages, like Haskell, that allow "infinite" data structures, I set out to be able to do so in C# after learning how yield
works.
- Take a look at the src\LazySequence to see the documented public API.
- All examples can be found in samples/Samples.
Taking an example from Math, consider an arithmetic progression:
// Create a sequence of all positive integers.
IEnumerable<int> allPositiveIntegers = LazySequence<int>.Create(
firstElement: 1,
(prev, index) => (prev + 1, false));
LazySequence
allows you to create a sequence through an 'equation' where you specify the first element, and a function to compute every successive element.
In this case:
- The first element is
1
. - We provide a method that takes the previous element, and the index of the element we need to return. We return a tuple of:
- The next element, which here is
prev + 1
. - A bool to indicate whether the sequence has ended, here we do not want the sequence to end, so we always return
false
.
- The next element, which here is
Why is it cool? Because allPositiveIntegers
above is now a never-ending* enumerable! (*restricted by ulong
and memory). Which means it can be used the following way:
foreach (var element in allPositiveIntegers)
{
// this loop will iterate through all integers
// possible in `int`
Console.WriteLine(element);
}
And since it is an IEnumerable
, we can also take advantage of LINQ
// sum of first 100 positive integers
var sumOfFirstHundredIntegers = allPositiveIntegers
.Take(100)
.Aggregate((acc, el) => acc + el);
As cool as arithmetic and geometric progressions may be, they don't really appear that commonly in day-to-day work sadly :(
But Lazy sequence can be used in more practical scenarios as well! With the ability to pass state along with the enumeration, it can be used as far as your imagination can take you!
A couple to highlight:
See samples\Samples/ObjectGeneration.cs
/*
* Consider a scenario where you need to generate unique names.
*/
IEnumerable<string> uniqueNames = LazySequence<string>.Create(
string.Empty,
(prev, idx) => ($"name_{idx}", false));
See samples\Samples\AsyncSample.cs
/*
* An AsyncLazySequence can be used as a medium to lazily paginate
* over web requests to your API.
*/
var pageSize = 10;
IAsyncEnumerable<object?> paginatedServerRequestCreator = AsyncLazySequence<object?, int>.Create(
firstElement: null,
initialState: 0,
async (prev, currentOffset, index) =>
{
var serverResponse = await ServerPageRequest(currentOffset, pageSize);
return (
nextElement: serverResponse,
iterationState: currentOffset + pageSize,
isLastElement: false);
});
Open an issue! I'm very open to feedback. I made this as a learning project, but if this can be made into a tool worth using, I'm willing to put in the work :)