lua-users home
lua-l archive

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


Hi,

Looking at the implementation of module it looks like it actually does place the module name in the global namespace. But that seems problematic for the reason mentioned here before. If I <<require "a">> then <<require "b">>, if "a" requires "c" and then "b" requires something different called "c" (because it fiddled with the path and looked someplace different), now "a" is using the wrong "c", right? Or am I missing something about how setfenv() works? I admit that I am having trouble understanding how setfenv() helps setting up an environment for an entire module when you just set it on a single function.

Underlying the package proposal, there is the assumption that there is a
one-to-one mapping between names such as "a.b" and modules residing
somewhere (such as "/usr/share/lua/5.0/a/b.lua", or
package.preload["a.b"]). There is also a caching mechanism, so that
requiring the same module a second time will be very efficient. Usually,
paths are set at startup. Fiddling with the path can have weird effects,
such as what you mention. However, it is "b" is the one that will use
the wrong "c", because "c" is already loaded and require() will not try
to load the new "c" from the new path.

In any case, the standard way to use require is to have a sequence of calls in your module

    local a = require"a"
    local b = require"b"
    ...
    module("foo")
    ...
    function bar()
    ...
    end

That way, no matter what happens, foo has a local reference to each of
the modules it needs. The setfenv simply causes bar() to end up in the
module namespace, instead of in the globals' table.

If there is anything you would like to be able to do when you package
your libraries, but feel you can't do with our proposal, this is the
right venue to talk about it. Chances are we can figure out how to do it
so that everything is compatible.

Thanks for the help so far. My big issues still have to do with isolating namespaces. For instance, what about the problem I mention above? Are modules required by "b" isolated from those required in "a", like they are in Python?

No. All modules are available globally. If both "a" and "b" require"c",
both will share the same module. That said, Lua is powerful enough for
you to override this behavior. I believe VEnv, used with CGILua, does that. Once again, Lua gives you the power. If you need a sandbox, it can be done.

Also, has anyone made a proposal for how you can promote all the members of "a" into the namespace of the module that requires "a"?

There is no standard way of doing this. The naive idea of doing
something like

    local a = require"a"
    for i,v in pairs(a) do
        _G[i] = v
    end

does not work. That is because within "a", functions might be
referencing symbols through the namespace table directly, so that if you
change one of the exported symbols, "a" might not see the change. This
is not true of all modules, but I wouldn't bet on it working everywhere.

On the other hand, it would be trivial to change the behavior of
module() so that, instead of seting the environment to the namespace
table, it used the globals' table instead.

The problem is moving a module from it's namespace to the globals'
table...

[]s,
Diego.