Reputation: 1037
I am trying to understand how the generator functions work in dart/flutter.
There is a video from the flutter team Generator Functions - Flutter in Focus where they discuss the following example.
Iterable<int> getRange(int start, int finish) sync* {
if (start <= finish) {
yield start;
print('start: $start');
for (final val in getRange(start+1, finish)) {
yield val;
print('val: $val');
}
}
}
only without the print lines.
I went and called that function in a main like this
void main() async {
getRange(0, 3).forEach(print);
}
and got the following results:
0
start: 0
1
val: 1
start: 1
2
val: 2
val: 2
start: 2
3
val: 3
val: 3
val: 3
start: 3
The part from where I do not understand the output result is from
1
val: 1
start: 1
Why is the start: 1
after the val: 1
. I somehow do not get how the recursion in combination with the yield works. Also what happens when the yield val;
gets read.
Upvotes: 0
Views: 861
Reputation: 31229
A good example of badly written code, doing strange things, is hard to understand because the code is badly written in the first place. To make debugging easier, I added the start
variable to the print
statements. Also removed async
from your main()
since nothing here is running asynchronously:
Iterable<int> getRange(int start, int finish) sync* {
if (start <= finish) {
yield start;
print('(start = $start) start: $start');
for (final val in getRange(start + 1, finish)) {
yield val;
print('(start = $start) val: $val');
}
}
}
void main() {
getRange(0, 3).forEach(print);
}
Which outputs:
0
(start = 0) start: 0
1
(start = 0) val: 1
(start = 1) start: 1
2
(start = 0) val: 2
(start = 1) val: 2
(start = 2) start: 2
3
(start = 0) val: 3
(start = 1) val: 3
(start = 2) val: 3
(start = 3) start: 3
So the part you are asking about is now:
1
(start = 0) val: 1
(start = 1) start: 1
An important detail in your program is that you are doing yield
BEFORE print()
. So when you are doing yield 1
, the value will move to your print
statement in main()
as the first thing. You can then see that your for-loop will do the val
print before asking for the next value which would make the start = 1
loop continue.
yield
in sync*
methods means the method deliver the value and stops executing the method until a new value is asked for.
Upvotes: 2