Общие внешние значения замыканий
Изучите несколько замыканий, использующих одно внешнее значение, и последствия его изменения.
«Общие внешние значения замыканий» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Что такое внешние значения?
- Общие внешние значения замыканий
- Функции-фабрики и генераторы
- Мемоизация с замыканиями