This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
sci4me's profile picture

getfenv(2) in Lua 5.2 and up

Started by sci4me, 01 March 2018 - 11:45 AM
sci4me #1
Posted 01 March 2018 - 12:45 PM
As I understand it, Lua 5.2 ditches set/getfenv. Pity.
Is it still possible to get the environment of the calling function (i.e. in the above stack frame)? In Lua 5.1 I just do getfenv(2) for this. How can I achieve this functionality in Lua 5.2+?
Lignum #2
Posted 01 March 2018 - 01:00 PM
You can't. Once a function has been created, there is no way to retrieve or set its environment. However, if you are loading the function with load (or loadfile), then you can pass a table in, which the function will use as its environment. This means that any changes the function makes will be visible in the table you passed in, and vice versa, so your table literally is the environment, not just a "template" of some sort.
sci4me #3
Posted 01 March 2018 - 01:38 PM
You can't. Once a function has been created, there is no way to retrieve or set its environment. However, if you are loading the function with load (or loadfile), then you can pass a table in, which the function will use as its environment. This means that any changes the function makes will be visible in the table you passed in, and vice versa, so your table literally is the environment, not just a "template" of some sort.

That's lame :/ Lua 5.1.5 is king!

So there's no way to get a unique identifier for the chunk that called a function in 5.2+? Because that's basically what I was using it for. Doesn't have to be the environment, I just need a way to identify the chunk calling my function… (can't use the debug library either)
Edited on 01 March 2018 - 12:43 PM
Exerro #4
Posted 02 March 2018 - 02:11 AM
A function (closure)'s environment is set when the closure is created, not when it's called, so I don't think getfenv would work anyway?

You could generate a stack trace with pcall and error and use that to get debug info of all the functions currently 'active'…?
sci4me #5
Posted 02 March 2018 - 02:43 AM
A function (closure)'s environment is set when the closure is created, not when it's called, so I don't think getfenv would work anyway?

You could generate a stack trace with pcall and error and use that to get debug info of all the functions currently 'active'…?

Well in Lua 5.1 it does; if you pass 2 to getfenv, it returns the environment of the calling function. I.e. the function above the function calling getfenv. If you pass 1, you get the environment of the function calling getfenv.
Edited on 02 March 2018 - 01:43 AM
Exerro #6
Posted 02 March 2018 - 10:11 AM
Ah I forgot about that. I think error is the way to go though without getfenv. If you can control the source name, even better.
SquidDev #7
Posted 02 March 2018 - 10:17 AM
Ah I forgot about that. I think error is the way to go though without getfenv. If you can control the source name, even better.
error only allows you to get the file name, not access the parent environment. getfenv allows you to do some interesting things like:

local function do_something()
  local configuration = getfenv(2).configuration --# Extract configuration object from caller's environment
  print("Running with " .. configuration.some_field)
end
That being said, the whole thing does feel a little too "magic" for my tastes. Include tails calls (and LuaJ's handling of them) in the mix, and it just ends up being easier to pass things explicitly :)/>.
Exerro #8
Posted 02 March 2018 - 12:40 PM
He only needs to uniquely identify the caller, which a source name could do fairly well.
sci4me #9
Posted 02 March 2018 - 07:57 PM
But it needs to work in Lua 5.2+ so.. yknow.. :P/>