lua-users home
lua-l archive

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


On Mon, Nov 18, 2013 at 11:00:27PM +0000, Sir Pogsalot wrote:
> Sven (and subsequently Sean):
> 
> I've been trying to communicate to you that toying with _ENV or creating a
> new _ENV that "falls through" to the original is not always appropriate
> when I'd like to globalize all (or select) functions from a module.
>  Especially when working within sandboxes or other strange environments
> prepared for you.  It's not a question of "do I want to do this", it's an
> uncertainty about how I might mess up the behavior of the environment by
> polluting _ENV.

Instantiating a new _ENV is no differrent than what you're suggesting, in
terms of potential conflicts with the inherited environment. And the whole
_point_ of lexical _ENV is to allow you to do _exactly_ what you're asking.

I think lexical _ENV is one of the coolest language features I've seen
recently. I would use it more if it weren't for being stuck with Lua 5.1 at
work, and for my open source projects wanting to remain compatible with
LuaJIT.

You could literally just do

	local _ENV = import(_ENV, io, "prefix_")

Your _ENV changes are lexically bound. They don't alter the environment of
your sandbox.


> I'm just going to go with the argument that local access is faster than
> global access? Yay! Glad we settled that :-)

You can reduce global lookups by at least half simply by doing

	local string = string
	local table = table
	...

Do you bother doing that? If not, is it because you're placing performance
over brevity?

Using _ENV, technically (if we want to assuage our performance daemons)
we've asymtopically approached 0 lookups if we assumed that some code does
lookups like a.b.c.d.e, which could be reduced to a single lookup into _ENV
populated by your import function.

If this particular kind of performance is really king, why aren't you using
a Lua implementation (i.e. LuaJIT) that gives that performance without even
requiring any language changes?

And LuaJIT does this more elegantly in an important sense. You're solution
doesn't work for objects with method tables, only straightup function calls
pulled from the environment. But, speaking for myself, I'd be far more
interested in speeding up method name lookups, because they happen much more
often in my code. But I certainly wouldn't do

	local method = object.method
	...
	method(object)

because that would be liable to break all kinds of things.

<snip>
> I'm sure it would take a lot of work to make this possible, I'm
> just trying to assert that there is a need.  I don't agree that doing this
> through _ENV or just dealing with it is a proper solution.

IIRC, early on in the Lua 5.2 release cycle there was a "with X do"
statement. This quickly morphed into lexical _ENV. Your feature was
effectively added, just not using the precise, character-for-character
syntax that you want. Lua instead came up with an elegant solution that
solved multiple problems at once, including getting rid of the awkward
setfenv/getfenv. And all without having to complexify the implementation.

Maybe you're hung up on tweaking locals and upvalues, because you're
thinking you can have your cake and to eat it, too (all the brevity and all
the performance). But _ENV is a special local upvalue. It's what provides
the hook to let you do exactly what you propose. And it's as performant as
Lua cares to be.

I know lots of people are piling on and attacking this proposal. But it
really is problematic: 1) _ENV provides exactly what you want, it's just not
super, duper fast, and 2) import doesn't solve the function lookup
performance "issue" in a generic manner because OOP code doesn't benefit.

Yes, locals are fast in Lua, but that's not their function. Their function
is to provide lexical name resolution. The way to extend lexical resolution
is with _ENV. End of story. Adding a complex language feature merely to
improve performance was a doomed proposal from the start.