[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: a new proposal for environments
- From: David Manura <dm.lua@...>
- Date: Thu, 25 Feb 2010 00:03:44 -0500
On Wed, Feb 24, 2010 at 6:38 PM, Roberto Ierusalimschy wrote:
> After that long discussion about setfenv/getfenv, we are convinced
> that both functions should belong to the debug API. Both clearly break a
> function's abstraction, tampering with the "original meaning" of the
> function.
In [1], one of the recurring problems was the desire to change the
environment lexically on a block or expression, but Lua 5.1 only
allowed the environment to be changed on a per-function basis. This
necessitated messing with the environment of the enclosing function
(possibly dangerous) or defining a nested function to apply that
environment to (more costly and verbose, though cleaner):
local o = with(shape)( rectangle { point(0,0), point(3,4) }
):endwith() -- modify outer env
local o = with(shape)(function() return rectangle { point(0,0),
point(3,4) } end) -- modify inner env
The _ENV or in/do proposals eliminate that restriction, at least on
blocks, leaving us with
local o
do
local _ENV = with(shape)
o = rectangle { point(0,0), point(3,4) }
end
Another case of this is, as I sometimes see, placing two modules or
classes into the same chunk (without enclosing anonymous functions to
separate the two):
module("one", package.seeall)
function a() <code1> end
module("two", package.seeall)
function b() <code2> end
Determining how that behaves requires some thought because the
environment of the enclosing chunk dynamically changes. A cleaner
design might have been something like similar to the previous example:
local one = module("one", _G, function()
local x = 1
function a() print(x); x=x+1 end
end)
local two = module("two", _G, function()
function b() print "b" end
end)
So how does the _ENV proposal affect module definition? This seems
less cohesive:
local one; do
local _ENV = module("one", _ENV)
local x = 1
function a() print(x); x=x+1 end
one = _ENV
end
local two; do
local _ENV = module("two", _ENV)
function b() print "b" end
two = _ENV
end
Yet another case for environments (getfenv) is to do string interpolation:
printf("Hello $name, the value of key $k is $b!\n", _ENV);
Unfortunately, it doesn't grab locals. It would be nice to have
something analogous like
local a,b,k,name = ...
printf("Hello $name, the value of key $k is $b!\n", _LOCALS);
compile down to bytecode equivalent to
local a,b,k,name = ...
local _LOCALS = {a=a,b=b,k=k,name=name}
printf("Hello $name, the value of key $k is $b!\n", _LOCALS);
I think someone recommended something like that recently. Though it's
possible to do via the debug library, it's also possible to do merely
by compile-time transformation like the above. That's provided you
don't have too many locals, so maybe full scale macros are preferred.
[1] http://lua-users.org/wiki/TableScope
[2] http://lua-users.org/wiki/StringInterpolation