[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Explanation needed for setfenv replacement for Lua 5.2
- From: Lorenzo Donati <lorenzodonatibz@...>
- Date: Wed, 04 May 2011 22:00:07 +0200
Peter & Edgar:
Thank you very much for the useful and detailed explanations.
On 04/05/2011 19.30, E. Toernig wrote:
Lorenzo Donati wrote:
I need some help in understanding some Lua code Sergey Rhozenko posted a
while ago. They are two version of 'setfenv' to use with upcoming Lua
5.2 in order to replace the missing library function.
I just hope, that people using such code know what they do.
But anyway ...
[snip]
With that background, one can see that there are usually better ways
to handle the environment in Lua 5.2 - especially if you want to
modify the env for a handful of functions:
Yes, I know. Thanks.
Although I appreciate the improvement in upcoming 5.2 regarding globals
management (_ENV etc.) for common uses, i.e. when the old environment is
to be changed lexically, I still found setfenv/getfenv extremely useful
for a very specific pattern, where the change is to be done dynamically.
Please, consider the following toy code:
---------------------------
-- (simplified) module simulation
-- (just to run the example in a single file)
simulated_require = function()
local M = {}
local function DslInterpreter( closure )
local private_data = {}
local env = {}
function env.AddItem( item )
table.insert( private_data, item )
end
function env.PrintResult()
print( table.concat( private_data, ' ' ) )
end
setfenv( closure, env )
closure()
end
M.Interpreter = DslInterpreter
return M
end
-- client code:
local lib = simulated_require 'mymodule'
local AN_UPVALUE = 'This is a silly DSL!'
lib.Interpreter( function() -- anonymous closure to emulate scoping
-- DSL fragment
AddItem 'hello!'
AddItem( AN_UPVALUE )
AddItem 'Hope You Enjoy!'
PrintResult() --> hello! This is a silly DSL! Hope You Enjoy!
end)
--------------------------------
Note that this pattern, to my knowledge, cannot be replaced using 5.2
loadin, since AN_UPVALUE is referenced inside the DSL fragment.
Even in the absence of upvalues, loadin incurs the overhead of
recompiling the chunk, if that chunk must be run in different environments.
Moreover, this pattern allows resusing the closure with a different
environment, if the need arise (e.g., debugging the DSL code with
different bindings, etc.). Or even with a different Interpreter.
Well, if 5.2 provided a function like, for example, callin(env,func)
analogous to loadin, but which takes a closure instead of a string
representing the chunk, I could probably ditch these setfenv/getenv
replacements, since I use them only for this specific pattern (and
variants). Maybe loadin could also be changed to do the right thing if
fed with a closure instead of a string: loadin(env,func)
I doubt that Lua team will introduce such a thing :-), so I must live
with my substitutes (thanks to Sergey Rhozenko!).
P.S: I know that I could pass the environment as an argument to the
anonymous closure like this:
------------------------------------
lib.Interpreter( function( env )
_ENV = env
-- DSL fragment
AddItem 'hello!'
AddItem( AN_UPVALUE )
AddItem 'Hope You Enjoy!'
PrintResult() --> hello! This is a silly DSL! Hope You Enjoy!
end)
------------------------------------
but this is less clean to me: not only the user must remember what to do
with the argument to the anon closure, but it adds cluttering
boilerplate code. The user of the DSL shouldn't be concerned with that
stuff.
Keep in mind that the anon closure could also come from loading a chunk
from an external file (yes, there is 'loadin' for that, but then you
have to do things in two different ways, depending on whether you load a
chunk or use an explicit anon closure).
[snip]
I.E. if you want to change the env for a complete module just add a simple
setenv function to its module table and be done:
function M.setenv(t) _ENV = t end
Ciao, ET.
PS: I still not sure if a "function environment" is The Right Thing.
I would prefer a simple thread-wide "setglobals" ;-)
Cheers
--
Lorenzo