www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - generate with state

reply Freddy <Hexagonalstar64 gmail.com> writes:
Is there a version of 

Nov 02 2015
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/02/2015 03:56 PM, Freddy wrote:

 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): 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
Nov 02 2015
parent reply Freddy <Hexagonalstar64 gmail.com> writes:
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?
Nov 02 2015
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Nov 02 2015