Генераторы¶
Генераторы - это корутины, которые могут вернуть ноль или более значений.
Функции-генераторы объявляются с использованием ключевого слова generator
.
Внутри генераторов можно использовать оператор yield
, который используется для порождения очередного значения генератором.
Значение (или ссылка), переданные в yield
, возвращаются вызывающему генератор коду.
Оператор этот не терминальный - возможно продолжение исполнения кода после него.
Пример функции-генератора с оператором yield
:
fn generator GenNumbers() : i32
{
yield 1;
yield 2;
yield 3;
}
На низком уровне оператор yield
заполняет результирующее значение и приостанавливает выполнение генератора, возвращая управление вызывающей стороне.
Вызывающая сторона при этом извлекает значение, порождённое yield
.
Внутри генераторов можно также использовать оператор return
.
Оператор return
без значения просто переведёт генератор в завершённое состояние.
Оператор return
со значением аналогичен комбинации yield
и пустого return
.
Если в функции-генераторе нету return
, он будет порождён неявно - в конце функции, по аналогии с return
для обычных функций, возвращающих void
значение.
fn generator GenNumbers(bool cond) : i32
{
yield 1;
if( cond )
{
return;
}
else
{
return 2; // аналогично yield 2; return;
}
}
Вызов генератора¶
Значения из генераторов извлекаются при помощи оператора if_coro_advance.
Поскольку генераторы могут порождать целые последовательности значений, имеет смысл использовать этот оператор в цикле.
Если же управление коду внутри оператора if_coro_advance
передано не было, то это означает, что генератор завершился.
Тип генератора¶
Тип генератора - это тип объекта-генератора. Функции-генераторы возвращают объекты типа генератора.
В Ü существует специальный синтаксис для указания типа генератора.
Состоит он из ключевого слова generator
, опциональной нотации для указания внутренних ссылок, опционального non_sync
тега, типа (с учётом ссылочности) возвращаемого значения.
type IntGen= generator : i32; // Простейший генератор
var [ [ char8, 2 ], 1 ] return_references[ "0a" ];
type FloatRefGen= generator'imut' : f32 & @(return_references); // Генератор, возвращающий ссылку и хранящий внутри себя ссылки.
type NonSyncRefGen= generator'mut' non_sync : u64 &mut @(return_references); // non_sync генератор, возвращающий изменяемую ссылку и хранящий внутри себя изменяемые ссылки.
Как можно заметить, тип генератора не определяется конкретными особенностями конкретного генератора (как он был создан). Это позволяет использовать одну и ту же переменную для хранения генераторов, порождённых разными функциями-генераторами с разным телом и разными параметрами.
// Функции-генераторы. Тип их возвращаемого значения - (generator : i32).
fn generator Foo(i32 x, i32 y) : i32;
fn generator Bar() : i32;
// Функция, возвращающая значения типа генератора, но не являющаяся генератором.
fn CreateGen(bool cond) : (generator : i32)
{
return select(cond ? Foo( 14, 56 ) : Bar() );
}