A couple days ago I had a fun idea running through my head. What if one could take the standard linq function Concat() and have it “consume” its own output as the input which created the output, a paradoxical call if you will. This can be represented with the following F# like pseudo-code:
Let y be 1…100
Let x be y.Concat(x)
While this can not be done in C# directly, via a little trickery with a lambda and a modified closure it is possible.
static void Main() { /*Pseudo code * Let y be 1 ... 100 * Let x be y.Concat(x) */ var oneToHundred = Inc(0).Take(100); IEnumerable x = null; var oneToHundredRepeated = oneToHundred.Concat(DelayedAssignment(()=>x)); x = oneToHundredRepeated; foreach (var i in oneToHundredRepeated) { //Write 1..100 out to the console over and over Console.WriteLine(i); Thread.Sleep(10); } } private static IEnumerableInc(int startingValue) { yield return startingValue + 1; foreach (var i in Inc(startingValue +1)) { yield return i; } } private static IEnumerableDelayedAssignment(Func> enumerationGetter) { //This loop appears to be a waste of syntax, but really it causes the compiler to build a statemachine which //will not realize the state enumerationGetter until someone tries to enumerate over this method //better ways of doing this, but this is the easiest foreach (var value in enumerationGetter.Invoke()) { yield return value; } }
Modifying the closure makes the call to Concat no longer functional and thus difficult to reason about. However, it is still quite a cool trick.