Hi everyone,
I put this topic in the general C# thread because it involves some trouble I have with laziness (of a method, not of me!)
In the mentoring guidance for the Accumulate exercise, one solution doesn’t involve the yield
keyword:
using System;
using System.Collections.Generic;
public static class AccumulateExtensions
{
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
{
var accumulated = new List<U>();
foreach (var element in collection)
{
accumulated.Add(func(element));
}
return accumulated;
}
}
Yet, this solution doesn’t pass the test cases, as the solution is required to be lazy:
Laziness test
Since accumulate
returns an IEnumerable
, it’s execution is deferred until ToList()
it is called on it, which is tested with the Accumulate_is_lazy
method
With the following test:
var counter = 0;
var accumulation = new[]
{
1,
2,
3
}.Accumulate(x => x * counter++);
Assert.Equal(0, counter);
accumulation.ToList();
Assert.Equal(3, counter);
Which returns for the given guidance solution:
Assert.Equal() Failure
Expected: 0
Actual: 3
I’m pretty new to lazy evaluations: is there a way to edit the guidance example method in a simple way that leads to it being lazy?
I’d be happy to submit a PR for addressing this issue but I don’t know how to solve it yet, I’d appreciate if someone could point me to some reading about it!
I can only think of writting a custom Enumerator that implements IEnumerator, but that makes the solution way more complicated and I guess anyone would use yield return
over it?
It there isn’t a simple way to make the guidance method lazy, maybe the simplest way to address the issue is to delete the ### Storing the results in an intermediate list
section of the mentor guidance?
Thanks!