Lua _G metatable не работает
Я пытаюсь контролировать интерактивную среду. Вот моя попытка:
home: lua
Lua 5.0.3 Copyright (C) 1994-2006 Tecgraf, PUC-Rio
> for n in pairs(_G) do io.write(n) end
stringxpcallLUA_PATHtostringgcinfoloadlibosunpackrequiregetfenvsetmetatablenext_TRACEBACKasserttonumberiorawequalcollectgarbagegetmetatable_LOADEDrawsetmathLUA_CPATHpcalldebug__powtypetablecoroutineprint_Gnewproxyrawgetloadstring_VERSIONdofilesetfenvpairsipairserrorloadfile>
> G=_G
> _G={}
> setmetatable(_G,{__index=G,__newindex=function() print("nope") end})
> for n in pairs(_G) do io.write(n) end
> x=3
>
Я ожидаю увидеть "Нет" после команды "х =3". Тем не менее, это проходит. Не пусто ли _G, и любой доступ / обновление _G будет проходить через определенные мета-методы?
1 ответ
Решение
Из руководства Lua 5.0:
_Г
Глобальная переменная (не функция), которая содержит глобальную среду (то есть
_G._G = _G
). Сам Lua не использует эту переменную; изменение его значения не влияет ни на какую среду. (Использованиеsetfenv
изменить среду.)
В частности, в интерактивном интерпретаторе Lua вам нужно setfenv( 0, new_global_env )
изменить среду текущего запущенного потока на new_global_env
,
Пример:
Lua 5.0.3 Copyright (C) 1994-2006 Tecgraf, PUC-Rio
> do
>> local rawget, print, _G = rawget, print, _G
>> local new_global_env = setmetatable( { tostring = tostring }, {
>> __index = function( t, k )
>> print( "get", k )
>> return rawget( _G, k )
>> end
>> } )
>> setfenv( 0, new_global_env )
>> end
> print( "hello" )
get print
hello
>
(Повышение rawget
, print
, а также _G
и новый tostring
глобальные необходимы, чтобы избежать бесконечной рекурсии.)