On 01/05/2012 09:27, Nick Sabalausky wrote:
A little write-up I just did on something I thought was pretty cool:
Combine Coroutines and Input Ranges for Dead-Simple D Iteration
https://www.semitwist.com/articles/article/view/combine-coroutines-and-input-ranges-for-dead-simple-d-iteration
This got me thinking, so I tried to do something a little similar
myself, the result is below.
If you only have one type to iterate over, you can make the user code
look even cleaner! I can't help but feel it can become even cleaner too.
(Scroll to the "User code" comment to miss out the implementation).
The code:
----
import core.thread;
class VFiber(Elem) : Fiber
{
Elem elem;
this(void delegate() dg)
{
super(dg);
}
}
auto visitor(T, Elem = T.visitType)(T t)
{
static struct Visitor
{
T t;
VFiber!Elem f;
@disable this();
@disable this(this);
this(T t)
{
this.t = t;
f = new VFiber!Elem(&t.visit);
f.call();
}
Elem front() @property
{
return f.elem;
}
void popFront()
{
f.call();
}
bool empty() @property
{
return f.state == Fiber.State.TERM;
}
}
return Visitor(t);
}
void yield(Elem)(Elem el)
{
auto f = cast(VFiber!Elem)cast(void*)Fiber.getThis();
if (f is null) throw new FiberException("Cannot yield a value from
outside the visit() method");
f.elem = el;
Fiber.yield();
}
// User code starts here
struct Iterable
{
string[] strs = ["hello", "world"];
alias string visitType;
void visit()
{
foreach(str; strs)
yield(str);
}
}
void main()
{
import std.stdio;
Iterable i;
foreach(el; i.visitor)
{
writefln("%s", el);
}
}
----
--
Robert
http://octarineparrot.com/