Dart Recursion
A special function called the dart generator enables us to generate a series of values. When we attempt to iterate over the iterators, a value is generated because generators return values on demand. Dart has two different kinds of generator functions built in.
- Synchronous Generators
- Asynchronous Generators
Synchronous Generator
It gives back an iterable object that updates synchronously with value. In addition to designating the synchronous generator function body as sync* to generator values, the yield keyword is employed.
Example
main() {
print("Dart Synchronous Generator Example.");
oddNumber(10).forEach(print);
}
// syn* functions returns an iterable
Iterable oddNumber(int num) sync* {
int k = num;
while(k >= 0) {
if(k%2 == 1) {
// 'yield' statement
yield k;
}
k--;
}
}
Output
Dart Synchronous Generator Example.
9
7
5
3
1
Explanation
We defined an oddNumber(10) Â function in the program above, using a for each loop without a body. The function will be iterated via the for each loop. As a synchronous generator function, we have now developed the oddNumber(10) function.
We started a new variable called k in the function body, and it is assigned the argument n. The code was then iterated using a while loop, and this was done until the value of k was equal to or less than 0.
The odd numbers from the generators were found by performing a modulus operation on k. Yield statements are used to halt the execution of a function and return a value one at a time. The value of each generator function run will be returned. The while loop ends and outputs the odd numbers when its condition is no longer true.
Asynchronous Generators
A stream object with asynchronous value carrying is returned by it. In addition to designating the asynchronous generator function body async* to generator values, the yield keyword is used.
Example
main() {
print("Dart Asynchronous Generator Example.");
asyncNaturalsTo(10).forEach(print);
}
// async* functions returns an stream object
Stream asyncNaturalsTo(int num) async* {
int k = 0;
while(k < num) {
// 'yield' statement
yield k++;
}
k--;
}
Output
Dart Asynchronous Generator Example.
0
1
2
3
4
5
6
7
8
9
Explanation
Values were created asynchronously by the code above. Each time the function body is executed, the asyncNaturalsTo(int num) function returns a stream object. In this instance, the yield keyword operated in the same manner as it did in the preceding example: it halted the function’s execution, returned the value, and then started it again for the subsequent iteration. This will continue till the function body is shut down.
Let’s comprehend these ideas regarding the generator function.
The yield Keyword
The generator function is still being executed by the yield; it just returns one item to the sequence at a time. After every time the generator function is run, it returns a value.
The sync* Keyword -
The synchronize generator function is declared using the sync* keyword. When we attempt to iterate over the value, it returns the value, not the one that was produced. Let’s examine the subsequent instance:
Example
void main() {
print('creating iterator');
Iterable numbers = getNumbers(4); // Here we are creating iterator
print('Iteration starts...');
for (int i in numbers) {
print('$i'); // Iterate over the iterator
}
print('end of main function');
}
Iterable getNumbers(int n) sync* { // define generator synchronously
print('generator started');
for (int i = 0; i < n; i++) {
yield i;
}
print('generator function ended');
}
Output
creating iterator
Iteration starts...
generator started
0
1
2
3
generator function ended
end of main function
Explanation
When we iterate over the iterator, the value is generated by the generator function mentioned before.
The async* Keyword
The asynchronous generators are declared with the async keyword. The stream object is returned. Let’s examine the subsequent illustration:
Example
void main() {
print('creating iterator');
Stream numbers = getNumbers(4);
print('starting to listen...');
numbers.listen((int k) {
print('$k');
});
print('end of the main function');
}
Stream getNumbers(int number) async* { // declaring asynchronous generator function
print('waiting inside generator a 3 seconds :)');
await new Future.delayed(new Duration(seconds: 3)); //sleep 3s
print('started generating values...');
for (int i = 0; i < number; i++) {
await new Future.delayed(new Duration(seconds: 1)); //sleep 1s
yield i;
}
print('ended generating values...');
}
Output
creating iterator
starting to listen...
end of the main function
waiting inside generator a 3 seconds 🙂
started generating values...
0
1
2
3
ended generating values...
Note: Copy the code above, then paste it into the dart editor. The distinction between synchronous and asynchronous generators is readily apparent.