Что такое генератор?

Генераторы — это шаблон, широко используемый в экосистеме Python, как и итераторы, они очень полезны для создания нескольких значений. Но в отличие от итераторов, они прерывают выполнение функции и позволяют вызывающей стороне возобновить ее выполнение позже:

Ключевое слово yield прерывает функцию и возвращает предоставленное значение. Теперь вместо использования функции next() для возобновления работы генератора вы можете использовать:

  • gen.send(value): ключевое слово yield вернет value при возобновлении
  • gen.throw(exc): ключевое слово yield вызовет exc при возобновлении
  • gen.close(): генератор не возобновляет работу (и поднимает StopIteration)

Примечание: это также называется сопрограммой.

Они являются мощным инструментом. На самом деле они использовались для параллелизма до появления async/await!

К сожалению, на момент написания этой статьи это все еще была нестабильная функция в Rust.

Представляем… генавайтера!



Благодаря нескольким полезным макросам этот ящик дает вам возможность нестабильной в стабильнойRust:

Как и в Python, макрос yield_! прерывает выполнение блока кода, функция gen.resume() возвращает перечисление GeneratorState с полученным значением или окончательным возвращаемым значением.

При вызове с gen.resume_with(arg) макрос yield_! вернет arg.

Последний трюк…

Все генераторы реализуют трейт Generator<Yield = Y, Return = R>. Если, как и я, у вас есть некоторый опыт работы с Python, вы хотели бы возвращать такие генераторы, возможно, сделать трейт с функцией для возврата таких генераторов, вот проблема:

  • вы не можете использовать impl Trait в псевдонимах типов или в сигнатурах трейт-функций (нестабильная функция)
  • вы не можете вернуть локальную переменную как &dyn Trait (переменная выходит за рамки, к счастью, это никогда не будет функцией)

На данный момент одним из решений является перемещение генератора в Box<dyn Trait>:

Заключение

Вам не нужно ждать, чтобы использовать эту функцию, genawaiter стремится стать «заменой» текущей нестабильной функции. Как только он станет общедоступным, нужно будет переименовать импорт.