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()

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)
      error("permission denied to access: "..tostring(key))

... 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.