Skip to content

Instantly share code, notes, and snippets.

@main--
Created September 8, 2015 00:31
Show Gist options
  • Select an option

  • Save main--/8e8aaffdef3c958c27a6 to your computer and use it in GitHub Desktop.

Select an option

Save main--/8e8aaffdef3c958c27a6 to your computer and use it in GitHub Desktop.
Emulate iterators using async/await
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
namespace Eaterator
{
class Program
{
private static IEnumerable<string> Testfunc()
{
return new EateratorAdapter<string>(Testfunc_inner);
}
static async void Testfunc_inner(IEaterator<string> _)
{
await _.yield_return("first");
for (int i = 0; i < 3; i++)
await _.yield_return("i: " + i);
var x = _.yield_return("second");
await _.yield_return("third");
await x;
}
private static IEnumerable<string> Bestfunc()
{
yield return "first";
for (int i = 0; i < 3; i++)
yield return "i: " + i;
var x = "second";
yield return "third";
yield return x;
}
static void Main(string[] args)
{
Console.WriteLine(Testfunc().SequenceEqual(Bestfunc()));
}
}
// -----------------------------------
// The ugly mess making this possible:
public interface IEaterator<T>
{
Yielder<T> yield_return(T t);
}
public class EateratorAdapter<T> : IEnumerator<T>, IEnumerable<T>, IEaterator<T>
{
public T Current { get; private set; }
object IEnumerator.Current { get { return Current; } }
private Action Continuation;
public EateratorAdapter(Action<IEaterator<T>> start)
{
Continuation = () => start(this);
}
public bool MoveNext()
{
var myCont = Continuation;
if (myCont == null)
return false;
Continuation = null;
myCont();
return Continuation != null;
}
Yielder<T> IEaterator<T>.yield_return(T t)
{
return new Yielder<T>(this, t);
}
internal void NextYield(T t, Action cont)
{
Current = t;
Continuation = cont;
}
// TODO:
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return this; }
IEnumerator IEnumerable.GetEnumerator() { return this; }
public void Reset() { throw new NotImplementedException(); }
public void Dispose() { }
}
public class Yielder<T> : INotifyCompletion
{
private EateratorAdapter<T> Parent;
private T Val;
public bool IsCompleted { get { return false; } }
public Yielder(EateratorAdapter<T> parent, T val)
{
Parent = parent;
Val = val;
}
public Yielder<T> GetAwaiter()
{
return this;
}
void INotifyCompletion.OnCompleted(Action continuation)
{
Parent.NextYield(Val, continuation);
}
public void GetResult()
{
}
}
}
@robot-2
Copy link

robot-2 commented Apr 28, 2016

fun iterator emulation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment