Hacker News new | ask | show | jobs
by klyrs 1941 days ago
This is how I view iterators, but with an extra notch in difficulty. You really need to understand the coroutine model to get anywhere -- and the same is true of iterators. Are these leaky abstractions? I generally think of leaks as "pushing", but this is "pulling" -- I'd call 'em sucky abstractions. But I digress.

I just sat down with the tutorial and banged out what I consider to be a holy grail for quality of life. Alas, it's about 50 lines of ugly boilerplate. I'm omitting it, in part because it's untested, but mostly because I'm embarrassed to share that much C++ in a public forum. If anybody close to the C++ standards is listening... please make this boilerplate not suck so hard.

    template<typename T>
    struct CoroutineIterator {
      left for the reader!
      hint: start with the ReturnObject5 struct in the article,
            and add standard iterator boilerplate
    }

    //! yields the integers 0 through `stop`, except for `skip`
    CoroutineIterator<int> skip_iter(int skip, int stop) {
      for(int i=0;i<stop;i++)
        if(i != skip)
          co_yield i;
    }

    int main() {
      for(auto &i : skip_iter(15, 20)) {
        std::cout << i << std::endl;
      }
    }
1 comments

So, given sibling comments on stack and function calls, this:

    skip_iter(int skip, int stop)
      for(int i=0;i<stop;i++)
Wouldn't work with complex types, boxed integers and so on? Because calling postfix ++ would be a function/method call?
Stackless coroutines can call other functions just fine (they would completely unusable otherwise). What they can't do is delegate suspension to any called function, i.e. any called function must return before the coroutine can yield as exactly one activation frame (the top level) can be suspended.
That's just a simple example. I think the following should work, possibly with modification for forwarding:

    class Stooge {...};

    CoroutineIterator<Stooge> three_stooges() {
       co_yield Stooge("Larry");
       co_yield Stooge("Curly");
       co_yield Stooge("Moe");
    }