Lua переменная видимость с setfenv - PullRequest
5 голосов
/ 23 июня 2010

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

Проблема, с которой я сталкиваюсь, заключается в том, что dofile всегда выполняется в реальной глобальной среде, поэтому внешние файлы просто бросают все свои объявления в _G.

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

function myFunc()
    print("In the sandbox:")
    print("Should be 1:", a)  -- falls back to _G for lookup
    a = 2  -- instantiating new global for sandbox
    print("Should be 2:", a)  -- from sandbox
    print("Should still be 1:", _G.a)  -- from host environment

    dofile("loading.lua")  -- here's where things go wrong

    print "\nBack in the sandbox:"
    print("Should be 3:", a)  -- changed by loadfile
    print("Should STILL be 1:", _G.a)  -- unchanged
end

a = 1
local newgt = {} -- new environment
setmetatable(newgt, {__index = _G})
setfenv(myFunc, newgt)
myFunc()

print("\nOutside of the sandbox:")
print("Should be 1: ", a)  -- in theory, has never changed

И файл, который он загружает (loading.lua:

print ("\nLoading file...")

print("Should be 2: ", a) -- coming from the sandbox environment
a = 3
print("Should be 3: ", a) -- made a change to the environment

И, наконец, вывод, который я вижу:

In the sandbox:
Should be 1: 1
Should be 2: 2
Should still be 1: 1

Loading file...
Should be 2:  1
Should be 3:  3

Back in the sandbox:
Should be 3: 2
Should STILL be 1: 3

Outside of the sandbox:
Should be 1:  3

1 Ответ

10 голосов
/ 23 июня 2010

Проблема, которую вы описываете, также обсуждается на этой странице Предложение пространства имен Dofile .Похоже, решением было заменить dofile:

function myapp.import(name)
  local f,e = loadfile(name)
  if not f then error(e, 2) end
  setfenv(f, getfenv(2))
  return f()
end

См. Также: Песочницы

...