lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Roberto Ierusalimschy wrote:
I will try to answer the sereval requests for our rationale for the
removal of setfenv/getfenv.
I'm happy using debug.getfenv/setfenv instead of the deprecated globals 
- but pretty please don't remove these as well. Just to throw some use 
cases into the pot for consideration...
I find myself needing to access module function environments for symbol 
import/export (Perl style -- i.e. controlling the exportable symbols via 
a list from the module being imported).
For OO; creating a function environment scoped "super" function which 
delegates to the parent class' method of the same name -- naive code:
add_method(Point3D, "move", function(self, x, y, x)
   super(self, x, y) -- injected into this environment by add_method()
end)

Control member access to a table/object depending on a caller's environment. In other words, sometimes you want to associate arbitrary data with a function (which can be hidden, if string keys are avoided), in this case so that you can ask: "is my caller marked for access to this resource?" -- more naive code:
local access = { }
local data = { }
setmetatable(object, {
   __index = function(_, key)
      local outer = getfenv(2)
      if outer[access] and outer[access][key] == object then
         return rawget(data, key)
      end
      error("permission denied to access: "..tostring(key))
   end
})

... where the caller function would need to have its environment suitably cooked with a fenv[access][key] = object. This is particularly convenient when you want to mark all functions in a module/class; doing it using tables will be pretty clunky in comparison.
There are probably other ways of doing the above, but although I really 
like the "in expr do ... end" construct (and I'll definitely be using 
it), I'll continue to (ab)use (debug.)getfenv/setfenv for a fair portion 
of my "make your own batteries" stuff.
Rich