Ford
Ford

Reputation: 2597

Lua environments when calling function within setfenv function

So I have a Lua script in which I set the environment of a function and define other functions that I make available in the environment. The issue is that when I call the function I did setfenv on, any function it calls within the environment uses the global _G environment to lookup values as opposed to the environment I set when calling the initial function. I have replicated the issue below:

> function f() print(t) end
> t = 5
> f()
5
> env = {}
> env['print'] = print
> env['t'] = 7
> env['f'] = f
> setfenv(f, env)
> f()
7
> setfenv(f, _G)
> f()
5
> function g() f() end
> g()
5
> setfenv(g, env)
> g()
5

Is there a way to get the environment to propagate to all calls without having to do setfenv on every function I want to add to env (basically, so that the last call in the example to g() would return 7 instead of 5)?

Using Lua 5.1.

Upvotes: 3

Views: 2095

Answers (1)

Egor Skriptunoff
Egor Skriptunoff

Reputation: 23747

You can write a function so that it automatically changes its own environment on every call

-- This code works on Lua 5.1, 5.2, 5.3
local getfenv = getfenv or function() end
local setfenv = setfenv or getfenv

a = 1

function f(env)
   local _ENV = env or getfenv(2) or _ENV; setfenv(1, _ENV)
   print(a)
end

env = { a = 2, print = print }

-- inherit environment for this call
f()    --> 1
-- set special environment for this call
f(env) --> 2
f()    --> 1

Or simply setfenv(1, getfenv(2)) if you are working only with Lua 5.1 and want to ALWAYS inherit environment.

Upvotes: 1

Related Questions