lua-users home
lua-l archive

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


The problem I have with the way it is being done in 5.2 is that it seems like the design is trying to solve a corner case problem.  Rather than solving the most common cases in a clear way and the uncommon cases in a unclear way, the _ENV table solves the common case in an unclear way and the uncommon cases in a *really* unclear way.  Yes it is useful on occasion to do something like:

parser = require "lpeg"

The problem I have here is that I just don't believe that is the normal thing to do.  Most of the time you want standard modules to be given a standard name.  If everyone has to assign a name to a module to load it you'll end up with all kinds of difficulties reading though different programs since everyone is using a different name.  Sure you'll end up with standard names most of the time, but why not make it work in a simple way most of the time and then provide a way to rename a module if you really need to?

It would seem to me that modules would be far clearer if you had to put them inside of an explicit code block just like in every other programming language, perhaps a keyword such as namespace like so:

return namespace
   function foo() ... end
   function bar() ... end
end

instead of

_ENV = {}
function foo() ... end
function bar() ... end
return _ENV


With an explicit namespace/end block you can now easily and clearly create multiple modules in the same file:

module1 = namespace
   function foo() ... end
   function bar() ... end
end

module2 = namespace
   function baz() ... end
end


Furthermore if I am concerned that some external code isn't properly using namespace/end and I want to prevent it from polluting my environment I can just surround the require itself in a namespace/end block like so:

m = namespace
require "some_module"
end

You could take it one small step further and say that if I am assigning the results of the require statement to a variable that is the same as wrapping the require statement in a namespace, so that the code below is 100% equivalent to the code above:

m = require "some_module"

Now I can call the code that was defined in the module like so:

m.module1.foo()

Or I can just import the modules into my environment like so:

mod1 = m.module1
mod2 = m.module2

The point here is that a namespace/end block is far clearer in intent, especially to those familiar with other languages, compared to setting the _ENV variable to an empty table.  I can also create multiple modules in the same file without going through any weird gyrations and it is 100% clear how to do so without having a full understanding of how the Lua language works.  In essence I believe that "foo = namespace function bar(x,y,z) ... end end" is the same as:

local M = _ENV
_ENV = {}
function bar(x,y,z) ... end
M.foo = _ENV
_ENV = M

Although I may not be understanding all the details of how _ENV works...


On Mon, Aug 9, 2010 at 7:32 PM, David Manura <dm.lua@math2.org> wrote:
On Sun, Aug 8, 2010 at 2:57 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
> Anyway, isn't this a continuation of the "referencing table elements
> within the same table constructor" thread?

The gist of that seemed to be to allow

 return {x = 2; y = function() print(x) end}

where print resolves to _G and x resolves to the table, which also
could be possible to resolve at compile time.  So, it is related.