Генераторы на основе сопрограмм
Используйте coroutine.wrap для создания ленивых последовательностей-генераторов.
«Генераторы на основе сопрограмм» — бесплатный урок Lua Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.
Зачем нужны генераторы на основе coroutine
Замыкания хорошо подходят для простых генераторов. Но если логика генерации требует вложенных циклов или сложного управления потоком, генератор на основе coroutine получается гораздо понятнее.
Основы coroutine.wrap
coroutine.wrap(fn) возвращает функцию. Каждый вызов возобновляет coroutine; значения, выданные через coroutine.yield, становятся возвращаемым значением.
local gen = coroutine.wrap(function()
coroutine.yield(1)
coroutine.yield(2)
coroutine.yield(3)
end)
for v in gen do print(v) endГенератор бесконечной последовательности
coroutine может выдавать значения бесконечно, поэтому отлично подходит для бесконечных последовательностей, выполнение которых вызывающий код завершает с помощью break.
local function naturals()
return coroutine.wrap(function()
local n = 0
while true do
n = n + 1
coroutine.yield(n)
end
end)
end
for v in naturals() do
if v > 5 then break end
print(v)
endГенератор обхода дерева
Рекурсивный глубокий обход с coroutine выполняется тривиально: просто выдавайте значения из рекурсивных вызовов, не управляя явным стеком.
local function walkTree(node)
return coroutine.wrap(function()
local function recurse(n)
coroutine.yield(n.value)
for _, child in ipairs(n.children or {}) do
recurse(child)
end
end
recurse(node)
end)
endГенератор чисел Фибоначчи
Последовательность Фибоначчи естественно реализуется как coroutine: храните две переменные состояния и выдавайте каждый следующий член.
local function fibs()
return coroutine.wrap(function()
local a, b = 0, 1
while true do
coroutine.yield(a)
a, b = b, a + b
end
end)
end
local fib = fibs()
for i = 1, 8 do print(fib()) endПередача значений в генератор
Аргумент возобновлённой функции становится возвращаемым значением yield, что обеспечивает двустороннюю связь.
local acc = coroutine.wrap(function()
local total = 0
while true do
local n = coroutine.yield(total)
total = total + (n or 0)
end
end)
acc() -- start
print(acc(10)) -- 10
print(acc(5)) -- 15coroutine.wrap и coroutine.create
wrap проще и вызывает исключение при ошибке. create возвращает объект потока и позволяет обрабатывать ошибки по возвращаемым значениям resume.
Конвейер генераторов
Объединяйте генераторы на основе coroutine в ленивые конвейеры: производитель выдаёт исходные данные, фильтр — подходящие элементы, а отображение — преобразованные элементы.
Распространение ошибок
Если обёрнутая coroutine вызывает ошибку, функция-обёртка также вызывает ошибку. Оберните вызов генератора в pcall для безопасного получения значений.
Эффективное использование памяти
Генераторы на основе coroutine являются ленивыми: они вычисляют значения по запросу. Это позволяет не создавать большие промежуточные таблицы и особенно полезно при работе с большими наборами данных.
Обработка исчерпания
Когда функция coroutine возвращает значение (а не выдаёт его), следующий вызов обёрнутой функции возвращает nil, естественным образом завершая общий цикл for.
Вопрос о генераторе на основе coroutine
Что происходит, когда функция coroutine генератора на основе coroutine.wrap возвращает значение (а не выдаёт его)?
Итоги: генераторы на основе coroutine
coroutine.wrap превращает любую coroutine в пригодную для повторного использования функцию-генератор. Это позволяет создавать ленивые бесконечные последовательности, рекурсивные обходы и этапы конвейера с понятным управлением потоком.
Часто задаваемые вопросы
Урок «Генераторы на основе сопрограмм» бесплатный?
Да — полный текст урока «Генераторы на основе сопрограмм» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.
Чему я научусь в уроке «Генераторы на основе сопрограмм»?
Используйте coroutine.wrap для создания ленивых последовательностей-генераторов. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Lua Academy?
Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Генераторы на основе сопрограмм»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Lua Academy?
Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Протокол обобщённого for
- Итераторы без состояния
- Итераторы с состоянием и замыканиями
- Генераторы на основе сопрограмм