Что такое генератор?
Генераторы — это шаблон, широко используемый в экосистеме 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 стремится стать «заменой» текущей нестабильной функции. Как только он станет общедоступным, нужно будет переименовать импорт.