Here is a simple generator in C#.
IEnumerable Foo()
{
int a = 1, b = 1;
while(true)
{
yield return b;
See here; example excerpt below:
module main;
import std.stdio;
import generators;
void genSquares(out int result, int from, int to)
{
foreach (x; from .. to + 1)
yield!result(x * x);
}
void main(string[] argv)
{
foreach (sqr; generator(&genSquares, 10, 20))
writeln(sqr);
}
There's no exact equivalent in D. Here are some rough equivalents:
Using opApply-style internal iteration. This doesn't allow iterating over two iterators in lockstep, though:
struct Foo {
int opApply(int delegate(ref int) dg) {
int a = 1, b = 1;
int result;
while(true) {
result = dg(b);
if(result) break;
int temp = a + b;
a = b;
b = temp;
}
return result;
}
}
void main() {
// Show usage:
Foo foo;
foreach(elem; foo) {
// Do stuff.
}
}
Use ranges. These are slightly harder to write in some cases, but are very efficient and allow lockstep iteration. This can also be iterated over with a foreach loop, exactly like the opApply version:
struct Foo {
int a = 1, b = 1;
int front() @property {
return b;
}
void popFront() {
int temp = a + b;
a = b;
b = temp;
}
// This range is infinite, i.e. never empty.
enum bool empty = false;
typeof(this) save() @property { return this; }
}
If you really need coroutine-style stuff you can combine ranges and opApply together using core.thread.Fiber, but you'll probably find that either ranges or opApply does what you need almost all the time.
The std.concurrency module now has a Generator class which makes this even easier (and you don't need a third-party library).
The class is an input range, so it can be used with for loops and all the standard std.range/std.algorithm functions.
import std.stdio;
import std.range;
import std.algorithm;
import std.concurrency : Generator, yield;
void main(string[] args) {
auto gen = new Generator!int({
foreach(i; 1..10)
yield(i);
});
gen
.map!(x => x*2)
.each!writeln
;
}