Как написать функцию-генератор, возвращающую последовательность 0,1,2,0,1,2?
Что проверяют
Понимаете ли вы, что генератор это ленивый итератор с сохранённым состоянием, а не функция, которая возвращает массив. Следом обычно просят обобщить решение до cycle(iterable) и спрашивают, как взять первые шесть значений из бесконечной последовательности, не повесив вкладку.
Как отвечать
Базовое решение в три строки:
function* cycle012() {
while (true) yield* [0, 1, 2];
}yield* делегирует обход массиву, и после двойки цикл начинается заново. Вариант со счётчиком: let i = 0; while (true) yield i++ % 3;. Вызов такой функции ничего не выполняет, а возвращает объект генератора. Код идёт до следующего yield только при вызове next(), который отдаёт { value, done }.
Что добавить, чтобы ответ был сильнее:
- обобщение:
function* cycle(iterable)сначала копирует значения в массив, потому что другой генератор можно пройти только один раз, затем крутит этот массив в бесконечном цикле. Пустой вход нужно проверить отдельно, иначеwhile (true)над пустым массивом зациклится, ничего не отдав; - потребление: с Iterator Helpers из ES2025 это
cycle012().take(6).toArray(), они есть во всех актуальных браузерах и в Node 22. Без них пишут свойtakeна генераторе илиfor...ofсbreak; - завершение:
breakвfor...ofвызывает у генератораreturn(), и блокfinallyвнутри него отработает. Это место для освобождения ресурсов; - без генератора: объект с
next()и[Symbol.iterator](), возвращающимthis, либо замыкание со счётчиком. Покажите, что генератор просто избавляет от этого шаблонного кода.
Где спотыкаются
Пишут [...cycle012()] или Array.from(cycle012()). Последовательность бесконечная, развёртка никогда не закончится и повесит поток.
Путают вызов функции с первым шагом: ждут, что cycle012() сразу вернёт 0, а получают объект, и значение лежит в .value результата next().
Используют один объект генератора в двух местах и удивляются, что у второго потребителя последовательность начинается не с нуля. Состояние общее, для независимого обхода нужен новый вызов функции.