Generators

23.1 Synchronous Generators (sync*)

Iterable<int> naturalsTo(int n) sync* {
  for (var i = 1; i <= n; i++) {
    yield i;
  }
}

Iterable<int> fibonacci() sync* {
  var (a, b) = (0, 1);
  while (true) {
    yield a;
    (a, b) = (b, a + b);
  }
}

Iterable<int> countdown(int n) sync* {
  if (n > 0) {
    yield n;
    yield* countdown(n - 1);       // delegate to another generator
  }
}

void main() {
  print(naturalsTo(5).toList());
  print(fibonacci().take(10).toList());   // lazy and infinite
  print(countdown(3).toList());
}

23.2 Asynchronous Generators (async*)

Stream<int> ticker(int count) async* {
  for (var i = 1; i <= count; i++) {
    await Future.delayed(const Duration(seconds: 1));
    yield i;
  }
}

Stream<String> readLinesSlowly(List<String> lines) async* {
  for (final line in lines) {
    yield line;
    await Future<void>.delayed(const Duration(milliseconds: 100));
  }
}

Future<void> main() async {
  await for (final t in ticker(3)) print('tick $t');
}