On Tue, May 20, 2014 at 6:05 AM, Choonster TheMage
<choonster.2010@gmail.com> wrote:
On 20 May 2014 14:31, Marc Lepage
<mlepage@antimeta.com> wrote:
Hi, looking for some thoughts on loading DSL style data.
I have it working but would like to swap out the environment when doing so, so it doesn't trample on the global environment.
I have something like:
function load(name)
local env = getfenv(0)
setfenv(0, dsl)
local data = "">
setfenv(0, env)
end
Where I get the thread's environment, set the dsl table (with all the DSL functions) as the environment, load the data (using require), then restore the environment (presumably the _G table). Of course I should really pcall the load instead of require, and return the data, but that's the idea.
This is using Lua 5.1.5. I understand that Lua 5.2 changes the way environments are handled?
If anyone could offer tips here or even better, point to a page which explains a lot of this in this context, that would be super great.
Thanks,
Marc
Could you load the file with `loadfile` instead of `require` and then set the environment of the loaded chunk with `setfenv` before executing it? If you need to turn a module name into a full path, you can use an implementation of Lua 5.2's `package.searchpath` function like the one from Steve Donovan's Penlight compat module[1].
If/when you move to Lua 5.2, you can pass the environment table directly to `loadfile` instead of using `setfenv`.
Regards,
Choonster
Thanks, Choonster.
Further reading late last night brought me to this answer, which has essentially the same suggestion (to loadfile, setfenv on the chunk, then call it).
I also found some code here
which checks the Lua version and in the case of 5.2, uses the newer (easier) technique you described.
Finally, a comment here
reveals the reason why my initial attempt didn't work, is that the functions use the environment they were compiled with, not the environment they were called from.
So I think it's all clear now and I've learned a reasonable amount about swapping function environments. I had the idea mostly correct but got tripped up in some details.
Cheers.
Marc