Jump to page: 1 2
Thread overview
Combine Coroutines and Input Ranges for Dead-Simple D Iteration
May 01, 2012
Nick Sabalausky
May 01, 2012
Rory McGuire
May 01, 2012
Jacob Carlborg
May 01, 2012
Robert Clipsham
May 01, 2012
Adam D. Ruppe
May 01, 2012
jerro
May 01, 2012
Nick Sabalausky
May 01, 2012
Sean Kelly
May 01, 2012
jerro
May 01, 2012
Nick Sabalausky
May 02, 2012
jerro
May 02, 2012
Rory McGuire
May 02, 2012
jerro
May 01, 2012
jerro
May 02, 2012
SomeDude
May 02, 2012
Nick Sabalausky
May 02, 2012
Nick Sabalausky
May 01, 2012
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


May 01, 2012
Fibers are basically just execution stacks like greenlets from python so I would imagine you can clone/copy them.

Nice write up, I think it will help people get more fibre in their D diet. :)

On Tue, May 1, 2012 at 10:27 AM, Nick Sabalausky < SeeWebsiteToContactMe@semitwist.com> 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
>
>
>


May 01, 2012
On 2012-05-01 10: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
>
>

Cool, that's how easy opApply should have been.

-- 
/Jacob Carlborg
May 01, 2012
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/
May 01, 2012
You might find this interesting too...

string yield(string what) { return `if(auto result = dg(`~what~`)) return result;`; }

    int opApply(int delegate(ref uint) dg) {
        for (int i = 0; i < array.length; i++)
                mixin(yield("array[i]"));

        return 0;
    }


The little mixin does the boilerplate making opApply
a bit more succinct, without anything really fancy.
May 01, 2012
On Tuesday, 1 May 2012 at 08:26:45 UTC, 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 is fun and all, but because of the horrible performance we really shouldn't be recommending people to use it.
May 01, 2012
"jerro" <a@a.com> wrote in message news:sxfngaqnhwxqookrvkif@forum.dlang.org...
> On Tuesday, 1 May 2012 at 08:26:45 UTC, 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 is fun and all, but because of the horrible performance we really shouldn't be recommending people to use it.

So it is bad performance?


May 01, 2012
On May 1, 2012, at 1:50 PM, Nick Sabalausky wrote:

> "jerro" <a@a.com> wrote in message news:sxfngaqnhwxqookrvkif@forum.dlang.org...
>> On Tuesday, 1 May 2012 at 08:26:45 UTC, 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 is fun and all, but because of the horrible performance we really shouldn't be recommending people to use it.
> 
> So it is bad performance?

Compared to normal iteration schemes, yes.  It may be comparable to opApply in terms of performance though.  If you're curious, look at the Fiber context switching code (starting at switchIn and switchOut).
May 01, 2012
On Tuesday, 1 May 2012 at 20:49:48 UTC, Nick Sabalausky wrote:
> "jerro" <a@a.com> wrote in message
> news:sxfngaqnhwxqookrvkif@forum.dlang.org...
>> On Tuesday, 1 May 2012 at 08:26:45 UTC, 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 is fun and all, but because of the horrible performance we really shouldn't be recommending people to use it.
>
> So it is bad performance?

It has bad performance compared to something like iota - I get
about 15 million iterations per second for this loop:

struct Iterable
{
     alias string visitType;

     void visit()
     {
         foreach(i; 0 .. 10_000_000)
             yield(i);
     }
}

...

foreach(el; visitor(i))
      sum ++;

 using Robert Clipsham's code, compared to billions iterations
per second with a regular loop. The problem is that people new
to D could see this, assume it performs similar to ranges like
iot and then wonder why their code is slow.
May 01, 2012
> Compared to normal iteration schemes, yes.  It may be comparable to opApply in terms of performance though.  If you're curious, look at the Fiber context switching code (starting at switchIn and switchOut).

It's much slower than opApply. This loop takes 70s on my machine:


foreach(el; visitor(Iterable(1000_000_000)))
    sum += 1;

And this one takes 2.7s:

auto iter(int n)
{
    struct I
    {
        int n;

        int opApply(int delegate(ref int) dg)
        {
            for(int i = 0; i < n; i++)
                if(int r = dg(i))
                    return r;
            return 0;
        }
    }

    return I(n);
}

foreach(el; iter(1000_000_000))
    sum += 1;


« First   ‹ Prev
1 2