Georgios
Georgios

Reputation: 1037

Dart Generator Functions (yield / yield*)

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: 1after 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

Answers (1)

julemand101
julemand101

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

Related Questions