0Pricing
Lua Academy · Урок

Общие внешние значения замыканий

Изучите несколько замыканий, использующих одно внешнее значение, и последствия его изменения.

«Общие внешние значения замыканий» — бесплатный урок Lua Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.

Совместное использование одной внешней переменной

Два замыкания, определённые в одной области видимости, могут совместно использовать одну и ту же ячейку внешней переменной. Изменения одного замыкания видны другому.

local function makeGetterSetter()
  local value = 0
  local function get() return value end
  local function set(v) value = v end
  return get, set
end
local get, set = makeGetterSetter()
set(42)
print(get())  -- 42

Почему происходит совместное использование

Lua не создаёт отдельную копию внешней переменной для каждого замыкания. Все замыкания, созданные в одном блоке и указывающие на одну локальную переменную, совместно используют одну ячейку внешней переменной.

Шаблон наблюдателя через общую внешнюю переменную

Общая внешняя переменная может выполнять роль шины сообщений между несколькими замыканиями.

local count = 0
local inc = function() count = count + 1 end
local dec = function() count = count - 1 end
local get = function() return count end
inc(); inc(); dec()
print(get())  -- 1

Особенность переменной цикла

В цикле numeric for на каждой итерации создаётся новая локальная переменная цикла, поэтому замыкания захватывают независимые внешние переменные.

local fns = {}
for i = 1, 3 do
  fns[i] = function() return i end
end
print(fns[1](), fns[2](), fns[3]())  -- 1 2 3 (each closure has its own i)

Особенность переменной цикла while

В цикле while, если замыкание захватывает одну изменяющуюся переменную, все замыкания используют одну и ту же внешнюю переменную и видят её итоговое значение.

local fns = {}
local i = 0
while i < 3 do
  i = i + 1
  fns[i] = function() return i end  -- all share same i!
end
print(fns[1]())  -- 3 (not 1!)

Захват новой локальной переменной

Чтобы захватывать независимые значения в цикле while, создавайте новую локальную переменную внутри тела цикла.

local fns = {}
local i = 0
while i < 3 do
  i = i + 1
  local ci = i  -- new local per iteration
  fns[i] = function() return ci end
end
print(fns[1]())  -- 1, fns[2]() == 2

Шаблон модуля с общим состоянием

Модуль может предоставлять несколько функций, совместно использующих приватную таблицу состояния через внешние переменные.

local function makeStack()
  local data = {}
  return {
    push = function(v) data[#data+1] = v end,
    pop  = function() local v = data[#data]; data[#data]=nil; return v end,
    size = function() return #data end,
  }
end

Псевдонимы и изменения

Будьте осторожны: все замыкания, ссылающиеся на одну внешнюю переменную, сразу видят одни и те же изменения. Это удобно, но может привести к нежелательной связанности.

Идентичность внешней переменной

debug.upvalueid(f, n) возвращает уникальный идентификатор внешней переменной функции f с номером n. Два замыкания с одинаковым ID внешней переменной используют одну и ту же ячейку.

debug.upvaluejoin

debug.upvaluejoin(f1, n1, f2, n2) заставляет внешнюю переменную f1 с номером n1 использовать ту же ячейку, что и внешняя переменная f2 с номером n2. Это низкоуровневый инструмент отладки.

Практические шаблоны

  • Пары функций получения и установки, использующие приватную переменную.
  • Счётчик событий со сбросом, доступным через несколько замыканий.
  • Состояние модуля, совместно используемое несколькими функциями программного интерфейса.

Вопрос об общей внешней переменной

В одной области видимости созданы два замыкания — get и set, оба захватывают value. Если вызвать set(99), что вернёт get()?

Итоги: общие внешние переменные

Замыкания в одной области видимости совместно используют ячейки внешних переменных. Изменения сразу видны всем совместно использующим их замыканиям. Это основа инкапсуляции и состояния модуля в Lua.

Часто задаваемые вопросы

Урок «Общие внешние значения замыканий» бесплатный?

Да — полный текст урока «Общие внешние значения замыканий» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.

Чему я научусь в уроке «Общие внешние значения замыканий»?

Изучите несколько замыканий, использующих одно внешнее значение, и последствия его изменения. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Lua Academy?

Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Общие внешние значения замыканий»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Lua Academy?

Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

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

  1. Что такое внешние значения?
  2. Общие внешние значения замыканий
  3. Функции-фабрики и генераторы
  4. Мемоизация с замыканиями
← Назад к Lua Academy