Created
September 8, 2015 00:31
-
-
Save main--/8e8aaffdef3c958c27a6 to your computer and use it in GitHub Desktop.
Emulate iterators using async/await
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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() | |
| { | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
fun iterator emulation