Thread overview
generate with state
Nov 02, 2015
Freddy
Nov 03, 2015
Ali Çehreli
Nov 03, 2015
Freddy
Nov 03, 2015
Ali Çehreli
November 02, 2015
Is there a version of http://dlang.org/phobos/std_range.html#.generate with state.
November 03, 2015
On 11/02/2015 03:56 PM, Freddy wrote:
> Is there a version of http://dlang.org/phobos/std_range.html#.generate
> with state.

generate() already allows "callables", which can be a delegate:

import std.stdio;
import std.range;

struct S {
    int i;

    int fun() {
        return i++;
    }
}

void main() {
    auto s = S(42);
    writefln("%(%s %)", generate(&s.fun).take(5));
}

Prints

42 43 44 45 46

Shorter but more cryptic:

  ... generate(&S(42).fun).take(5)

If the generation process is naturally recursive like traversing a tree, then you may want to consider std.concurrency.Generator (which does not involve multiple threads at all):

  http://dlang.org/phobos/std_concurrency.html#.Generator

Here is an example:


http://ddili.org/ders/d.en/fibers.html#ix_fibers.Generator,%20std.concurrency

import std.stdio;
import std.range;
import std.concurrency;

/* This alias is used for resolving the name conflict with
 * std.range.Generator. */
alias FiberRange = std.concurrency.Generator;

void fibonacciSeries() {
    int current = 0;
    int next = 1;

    while (true) {
        yield(current);

        const nextNext = current + next;
        current = next;
        next = nextNext;
    }
}

void main() {
    auto series = new FiberRange!int(&fibonacciSeries);
    writefln("%(%s %)", series.take(10));
}

Ali

November 03, 2015
On Tuesday, 3 November 2015 at 00:08:54 UTC, Ali Çehreli wrote:
> generate() already allows "callables", which can be a delegate:
>
> import std.stdio;
> import std.range;
>
> struct S {
>     int i;
>
>     int fun() {
>         return i++;
>     }
> }
>
> void main() {
>     auto s = S(42);
>     writefln("%(%s %)", generate(&s.fun).take(5));
> }
>
> Prints
>
> 42 43 44 45 46

Will that allocate gc memory? Is there any why I pass state as a tuple and have my generator modify state as It's called?

November 03, 2015
On 11/02/2015 04:51 PM, Freddy wrote:
> On Tuesday, 3 November 2015 at 00:08:54 UTC, Ali Çehreli wrote:
>> generate() already allows "callables", which can be a delegate:
>>
>> import std.stdio;
>> import std.range;
>>
>> struct S {
>>     int i;
>>
>>     int fun() {
>>         return i++;
>>     }
>> }
>>
>> void main() {
>>     auto s = S(42);
>>     writefln("%(%s %)", generate(&s.fun).take(5));
>> }
>>
>> Prints
>>
>> 42 43 44 45 46
>
> Will that allocate gc memory?

Not the way I wrote it. You can test it by putting @nogc to the function that uses that code. (The only GC code up there is writefln).

> Is there any why I pass state as a tuple and have my generator modify state
> as It's called?

Yes but you must ensure that the object will live long enough. A closure is simple but it uses GC. The following code passes a temporary object and makeMyRange() closes over that variable:

import std.stdio;
import std.range;

struct S {
    int i;

    int fun() {
        return i++;
    }
}

auto makeMyRange(S s) {
    return generate(() => s.fun()).take(5);    // <-- closure
}

void main() {
    writefln("%(%s %)", makeMyRange(S(42)));
}

Alternatively, as long as it will live long enough, you can make a local object like 's' in my original code.

Ali