Instead of building an array containing all the values and returning them all at once, a generator yields the values one at a time, which requires less memory and allows the caller to get started processing the first few values immediately
A function is a generator if its body is marked with the sync*
or async*
modifier.
Dart has built-in support for two kinds of generator functions:
Iterable
object.Stream
object.To implement a synchronous generator function, mark the function body as sync*
, and use yield
statements to deliver values:
Synchronous generator returns an iterable.
// Synchronous generator: Returns an Iterable object.
Iterable<int> SequenceOfValues(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
void main() {
print(SequenceOfValues(5)); //(0, 1, 2, 3, 4)
}
To implement an asynchronous generator function, mark the function body as async*
, and use yield
statements to deliver values:
Asynchronous generator returns an stream.
// Asynchronous generator: Returns an Stream object.
Stream<int> SequenceOfValuesAsync(int n) async* {
int k = 0;
while (k < n) yield k++;
}
void main() async {
var result = await SequenceOfValuesAsync(5).toSet(); //convert to set
print(result); //{0, 1, 2, 3, 4}
}
If your generator is recursive, you can improve its performance by using yield*
:
Iterable<int> SequenceOfValues(int n) sync* {
if (n > 0) {
yield n;
yield* SequenceOfValues(n - 1);
}
}
void main() {
var result = SequenceOfValues(5);
print(result); // (5, 4, 3, 2, 1)
}