Канонической ссылкой для этого является текст ссылки . Объясняя это кратко, мы отработаем следующий код с сайта:
a = 1
local newgt = {} -- create new environment
setmetatable(newgt, {__index = _G})
setfenv(1, newgt) -- set it
Первая строка устанавливает (глобальную) переменную "a". Вы можете просмотреть это как настройку значений по умолчанию для вашего кода. (Имейте в виду, что в Lua все переменные являются глобальными, если вы не объявите их с помощью "local".)
Следующая строка создает таблицу, которая будет вашей новой средой. Он является локальным по отношению к функции / чанку, в которых вы выполняете, поэтому он не будет сброшен чем-либо еще, работающим сейчас или позже.
Третья строка - это начало магии. Чтобы понять это, вам нужно понять метаметоды В сущности, однако, вы используете метамагия Lua, чтобы гарантировать, что любые глобальные имена, которые не определены в вашей будущей функциональной среде, получат решен в контексте вашей старой глобальной среды. По сути, это означает, что если вы используете имя, которого нет в вашей функциональной среде, Lua будет автоматически охотиться в глобальной среде, в которой вы привыкли находить имя. (Одним словом: наследство.)
Четвертая строка - это то, где вы получаете то, что ищете. Setfenv (1, ...) означает, что это меняет среду для вашей текущей функции. (Вы можете использовать 2 для вызывающей функции, 3 для вызывающей функции и т. Д. На линии вверх.) Второй параметр - это таблица, которую вы только что создали, дополненная наследованием старого поведения. Ваша функция теперь выполняется в новой глобальной среде. В нем есть все имена и значения старой среды (в том числе функции и глобальная переменная «a», которую вы вводите). Однако, если вы ЗАПИШИТЕ имя, оно не будет перезаписывать глобальное состояние. Он перезапишет вашу локальную копию.
Рассмотрим следующий код:
a = 10
b = 20
То, что вы сделали сейчас, заставило вашу таблицу окружения функций выглядеть следующим образом:
{a = 10, b=20}
Ваша «глобальная» среда, короче говоря, содержит только две переменные: a (значение 10) и b (значение 20). Когда вы откроете «a» позже, вы получите локальную копию с 10 - старое глобальное значение, хранящееся в вашем метатабле, теперь затенено и по-прежнему установлено на 1 - а если вы откроете «b», вы получите 20, несмотря на то, что исходное глобальное состояние, вероятно, даже не имеет переменной "b" для доступа И вы все равно сможете получить доступ ко всем функциям и т. Д., Которые вы определили до этого момента.
Отредактировано для добавления тестового кода для устранения проблемы OP.
Я поместил следующий код в "junk.lua":
a = 1
local newgt = {}
setmetatable(newgt, {__index = _G})
setfenv(1, newgt)
print(a)
a = 10
print(a)
print(newgt)
Вывод будет следующим:
$ lua junk.lua
1
10
table: 0x976d040
Используется Lua 5.1.4. Какой вывод вы видите?