Problem with setfenv

a = 1
local newgt = {}        -- create new environment
setmetatable(newgt, {__index = _G})
setfenv(1, newgt)    -- set it
print(a)      --> 1

a = 10
print(a)      --> 10
print(_G.a)   --> 1
_G.a = 20
print(_G.a)   --> 20

So I have copied this code directly from: Programming in Lua : 14.3

Which states: In this code, the new environment inherits both print and a from the old one. Nevertheless, any assignment goes to the new table. There is no danger of changing a really global variable by mistake, although you still can change them through _G

It also shows that the first print call should return 1

However when running this code, I receive attempt to call a nil value when the first print call is hit.

Any idea why this is happening? I’m probably just being stupid

1 Like

Roblox advices you not to use setfenv and getfenv and move to ModuleScripts instead.

4 Likes

This happens because in Lua, _G has all of the environment functions, but in Roblox they have sandboxed it to be an empty table that is shared across scripts.

Basically, in your code, you are setting your current environment to an empty table with __index also as an empty table.

Edit:

a = 1;
local newEnv = setmetatable({}, {__index = getfenv()})
setfenv(1, newEnv)
print(a)

a = 10
print(a)
1
10

Hope this helps haha.

3 Likes

Attempt to call a nil value means you’re trying to call a function which does not exist, in this case it’s print. This is because you’ve created a new environment and not referenced the base meaning all globals will be nil.

local p = print
local newgt = {}        -- create new environment
setmetatable(newgt, {__index = _G})

p(print)   --> function: 00xxxx
setfenv(1, newgt)
p(print)   --> nil

In standard Lua, _G includes methods such as print while in Roblox it does not.

-- Standard Lua
print(print == _G.print)   --> true

-- Roblox Lua
print(print == _G.print)   --> false
2 Likes

Thanks @woot3 and @TacoBellSaucePackets

I was referencing the lua docs as linked in the original post for the environment
“the new environment inherits both print and a from the old one”

I think what @TacoBellSaucePackets explained is, _G doesn’t contain the environmental functions in Roblox, therefore the environment I was passing was actually just an empty table - thanks for helping me clear this up.