A subthread of the "Impressed" thread revolved around D's lack of a yield mechanism for iteration. Nick Sabalausky mentioned his earlier attempt to create a library based yield which unfortunately was too slow to compete with explicit opApply/ranges [1].

I took a shot at it. It's fast. The resulting code is reasonably pretty. But it doesn't provide a range interface, just opApply.

---
module yielder;

import core.thread;

/**
        Examples:
        ---
        import yielder;
        import std.stdio;
        
        auto y = new class Yielder!int {
                final void yielding() {
                        yield(0);
                        yield(13);
                        yield(42);
                }
        };
        
        foreach(x; y) {
                writeln(x);
        }
        ---
*/
class Yielder(E) {
        abstract void yielding();
        
        this() {
                this.fiber = new Fiber(&yielding);
        }
        
        private {
                Fiber fiber;
                int result;
                int delegate(ref E) callback;
        }
        
        final int opApply(int delegate(ref E) cb) {
                callback = cb;
                result = 0;
                fiber.reset();
                fiber.call();
                return result;
        }
        
        final void yield(ref E value) {
                result = callback(value);
                if(result != 0) {
                        Fiber.yield();
                }
        }
        final void yield(E value) {
                yield(value);
        }
}
---

[1] https://semitwist.com/articles/article/view/combine-coroutines-and-input-ranges-for-dead-simple-d-iteration

Reply via email to