[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: modules, require, magic
- From: Hisham <hisham.hm@...>
- Date: Wed, 19 Oct 2011 19:15:32 -0200
On Wed, Oct 19, 2011 at 6:24 PM, Roberto Ierusalimschy
<roberto@inf.puc-rio.br> wrote:
>> Certainly an improvement from handling the module table explicitly
>> (and no segfaults this time). But having basically the same function
>> being provided by the loader[1] would obviate the need for explicitly
>> mentioning _ENV.
>
> I think explicitly mentioning _ENV is good. If you are working with
> a different global environment, why hide that information?
Fair. I could argue otherwise, but that's indeed more a matter of
taste, which I respect.
One remaining issue lies in the visibility of globals:
David Manura wrote:
>> Hisham wrote:
>> The module() function gave us an easy answer for the question "how do
>> I write a module" that mirror other languages that offer constructs for modularity.
>> [...] If module() is broken beyond repair and there is no clean way to add a
>> library function to do that, I'd dare to say that this is something
>> important enough that a language construct would be justifiable
>
> OTOH, there are multiple ways to use this function: The somewhat
> canonical "easy way" involves package.seeall, and maybe we should all
> just accept that, in the way in another life I just accept Perl 5.
> Josh's principle I think is important though: "[it's about] making it
> easier to do the right thing. With module it's easy to get things
> wrong".
Many of the complaints against module() are actually against
package.seeall. The issues of exposing unrelated globals through a
module and inheriting dependencies are caused by it. The module()
implementation you suggested leaves this question open, so my
suggestion in that front would be something along the lines of:
---------- variation on Roberto's module
function module (name, ...)
local env = package.loaded[name]
if env == nil then
env = {}
package.loaded[name] = env
end
env._NAME = name
env._M = env
for _, f in ipairs{...} do
env = f(env) -- <=== allow f to redefine env
end
return env
end
local lua_libs = {}
for k,v in pairs(package.loaded._G) do
lua_libs[k] = v
end
function package.seebase(mod)
local env = {}
setmetatable(env, {
__index = function(t,k)
return rawget(mod, k) or rawget(lua_libs, k)
end,
__newindex = mod
})
return env
end
----------
This proposed package.seebase exposes Lua standard libraries to the
module without exporting them. (I only had to make one slight change
to the module() function you posted; if that is doable without this
change I'd be happy to be corrected.) I think package.seebase brings
the benefits of package.seeall without its two big drawbacks mentioned
above.
I'd even argue that this should be the default behavior for module()
when called with a single argument, in line with David Manura's
concerns that the canonical "easy way" should help the user get things
right.
> Moreover,
> a modified 'load' function forces everyone to live with its magic.
Not necessarily; Fabio's original loader did this but loader5
restricted the magic to the users of module().
-- Hisham
http://hisham.hm/ - http://luarocks.org/
- References:
- modules, require, magic, Eduardo Ochs
- Re: modules, require, magic, Javier Guerra Giraldez
- Re: modules, require, magic, Petite Abeille
- Re: modules, require, magic, Sam Roberts
- Re: modules, require, magic, David Manura
- Re: modules, require, magic, Hisham
- Re: modules, require, magic, Roberto Ierusalimschy
- Re: modules, require, magic, Fabio Mascarenhas
- Re: modules, require, magic, Roberto Ierusalimschy
- Re: modules, require, magic, Hisham
- Re: modules, require, magic, Roberto Ierusalimschy