0Pricing
Lua Academy · Урок

Генераторы на основе сопрограмм

Используйте 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))   -- 15

coroutine.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 — локальная установка не требуется.

Все уроки этого курса

  1. Протокол обобщённого for
  2. Итераторы без состояния
  3. Итераторы с состоянием и замыканиями
  4. Генераторы на основе сопрограмм
← Назад к Lua Academy