Функции генератора дротиков используются для ленивой генерации последовательности значений по запросу. Такая последовательность значений может создаваться синхронно или асинхронно. Для поддержки обоих сценариев доступны два типа встроенных функций генератора:
Синхронный генератор: функция синхронного генератора возвращает Итерационный объект. Это означает, что сначала значения генерируются, а затем функция лениво возвращается по запросу.
Итерируемый: набор значений или «элементов», к которым можно обращаться последовательно.
Асинхронный генератор: функция асинхронного генератора возвращает объект Stream. Последовательность значений создается по запросу, когда они становятся доступными.
Поток: источник событий с асинхронными данными.
Видео на YouTube
Давайте разберемся с функциями генератора на примере. Мы будем генерировать числа, начиная с заданного числа, скажем от 5 до 0, используя функции генератора. Мы рассмотрим оба способа (асинхронный и синхронный генераторы) для создания этой числовой последовательности.
Использование sync*
- синхронного генератора
Функция Iterable<int> countDownFromSync(int num) sync*
принимает номер как num
и отправляет все числа, начиная с num
и заканчивая 0. Функция синхронного генератора отмечена sync*
. Значения возвращаются с использованием ключевого слова yield
. Итерируемый sequence
получает числовую последовательность и распечатывает каждое число с помощью цикла for
. Эта числовая последовательность фактически не создается до тех пор, пока к ней не обращается for
цикл.
main1 ():
void main1() { print("Getting CountDown Iterable [sync* + yield]"); Iterable<int> sequence = countDownFromSync(5); print("Starting..."); for (int value in sequence) { print(value); } print("DONE"); } //sync* Iterable<int> countDownFromSync(int num) sync* { while (num > 0) { yield num--; } }
Вывод:
sync*
помогает генерировать значения синхронным образом. Обратите внимание, что сообщение Starting...
печатается перед выполнением цикла. Наконец-то выполняется сообщение DONE
.
Getting CountDown Iterable [sync* + yield] Starting... 5 4 3 2 1 DONE
Использование async*
- асинхронного генератора
Функция Stream<int> countDownFromAsync(int num) async*
принимает номер как num
и доставляет номерную последовательность, начиная с num
до 0. Функция асинхронного генератора помечена async*
. Значения возвращаются с использованием ключевого слова yield
. Поток sequence
получает числовую последовательность. Доступ к его значениям можно получить, как только он начал прослушивание.
main2 ():
void main2() { print("Getting CountDown Stream [async* + yield]"); Stream<int> sequence = countDownFromAsync(5); print("Starting..."); sequence.listen((int value) { print(value); }); print("DONE"); } //async* Stream<int> countDownFromAsync(int num) async* { while (num > 0) { yield num--; } }
Вывод:
async*
помогает генерировать значения асинхронным образом. Обратите внимание, что сообщения / настройки Starting...
и DONE
печатаются до того, как будут напечатаны фактические значения потока. Значения печатаются по мере того, как они становятся доступными после кода настройки.
Getting CountDown Stream [async* + yield] Starting... DONE 5 4 3 2 1
Использование sync* + yield*
- Рекурсивный синхронный генератор
Когда функции генератора используются рекурсивно, yield*
используется для обозначения таких рекурсивных вызовов функций. В этом примере показано, как рекурсивно использовать функции генератора. Вы заметите тот же результат, что и для нерекурсивной реализации. Ключевое слово yield*
используется для функции, вызываемой рекурсивно.
void main3() { print("Getting CountDown Iterable [sync* + yield*]"); Iterable<int> sequence = countDownFromSyncRecursive(5); print("Starting..."); for (int value in sequence) { print(value); } print("DONE"); } //sync* + yield* for recursive functions Iterable<int> countDownFromSyncRecursive(int num) sync* { if (num > 0) { yield num; yield* countDownFromSyncRecursive(num - 1); } }
Вывод:
Getting CountDown Iterable [sync* + yield*] Starting... 5 4 3 2 1 DONE
Использование async* + yield*
- Рекурсивный асинхронный генератор
Это пример рекурсивного использования функции асинхронного генератора. Он также имеет тот же вывод, что и его нерекурсивный аналог.
void main4() { print("Getting CountDown Stream [async* + yield*]"); Stream<int> sequence = countDownFromAsyncRecursive(5); print("Starting..."); sequence.listen((int value) { print(value); }); print("DONE"); } //async* + yield* for recursive functions Stream<int> countDownFromAsyncRecursive(int num) async* { if (num > 0) { yield num; yield* countDownFromAsyncRecursive(num - 1); } }
Вывод:
Getting CountDown Stream [async* + yield*] Starting... DONE 5 4 3 2 1
Резюме
В этой статье мы увидели, как использовать функцию генератора Дарта для синхронного и асинхронного создания последовательности значений по запросу итеративным и рекурсивным образом.
Это все для этой статьи. Прочтите Dart Vocabulary Series, чтобы узнать о других материалах по Dart.
Исходный код
Пожалуйста, проверьте исходный код на Github здесь.
использованная литература
Happy Darting :)
_ Понравилась статья? Не нашли интересную тему? Пожалуйста, оставьте комментарий или напишите в twitter о темах, которыми вы хотите, чтобы я поделился!
Кстати, я люблю и кексы, и кофе :) _
Следуй за мной в Medium
Первоначально опубликовано на https://ptyagicodecamp.github.io 7 июня 2020 г.