Dart Generator Functions (yield / yield*)

Solution 1:

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.