1 module nxt.sample_fibers;
2 
3 import core.thread: Fiber;
4 
5 void fibonacciSeriesRef(ref int current)
6 {
7     current = 0; // Note: 'current' is the parameter
8     int next = 1;
9     while (true)
10     {
11         Fiber.yield();
12 /* Next call() will continue from this point */
13         const nextNext = current + next;
14         current = next;
15         next = nextNext;
16     }
17 }
18 
19 unittest
20 {
21     int current;
22     Fiber fiber = new Fiber(() => fibonacciSeriesRef(current));
23     import std.stdio;
24     foreach (_; 0 .. 10)
25     {
26         fiber.call(); // return
27         write(current, ", ");
28     }
29     writeln;
30 }
31 
32 import std.stdio;
33 
34 import std.concurrency: yield;
35 
36 void fibonacciSeries()
37 {
38     int current = 0; // <-- Not a parameter anymore
39     int next = 1;
40     while (true)
41     {
42         current.yield; // return
43         const nextNext = current + next;
44         current = next;
45         next = nextNext;
46     }
47 }
48 
49 unittest
50 {
51     import std.concurrency: yield, Generator;
52     auto series = new Generator!int(&fibonacciSeries);
53     import std.range: take;
54     writefln("%(%s, %)", series.take(10));
55 }
56 
57 struct Yields { string type; }
58 
59 @Yields("int")  // <-- better to specify type here than in caller
60 void fibonacciSeries2()
61 {
62     int current = 0;
63     int next = 1;
64     while (true)
65     {
66         current.yield; // return
67         const nextNext = current + next;
68         current = next;
69         next = nextNext;
70     }
71 }
72 
73 auto generator(alias func)()
74 {
75     import std.format: format;
76     foreach (attr; __traits(getAttributes, func))
77     {
78         import std.traits: isInstanceOf;
79         static if (is (typeof(attr) == Yields))
80         {
81             mixin (format("alias YieldedType = %s;", attr.type));
82             import std.concurrency: Generator;
83             return new Generator!YieldedType(&func);
84         }
85     }
86     assert(0, format("%s does not have a Yields attribute",
87                          func.stringof));
88 }
89 
90 unittest
91 {
92     import std.stdio;
93     import std.range: take;
94     auto series = generator!fibonacciSeries2; // <-- THIS TIME, NO 'int'
95     writefln("%(%s, %)", series.take(10));
96 }