lua-users home
lua-l archive

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


On Mon, Aug 16, 2010 at 9:42 AM, Petite Abeille
<petite.abeille@gmail.com> wrote:
> On Aug 16, 2010, at 2:38 PM, Jerome Vuarand wrote:
>>> (1) register module with _LOADED (lauxlib.luaL_pushmodule)
>>> (2) initialize module's _M, _NAME and _PACKAGE (loadlib.modinit)
>>> (3) execute options (lauxlib.dooptions)
>> OK.
> Ok. That must nearly qualify as unconditional consensus :)

On #2, I don't think I've mentioned any problems.  OTOH, I don't see
when they would ever be needed.  I believe _M is unnecessary in a
module's public interface (public table) but rather exists only to
assist a module's implementation under some styles of module
definition like the infamous package.seeall.  _M provides a module's
implementation a convenient reference to the module's public table
when the module's public table is not otherwise stored as a local
(e.g. `local M = {}`, `local M = module(...)` or in 5.2.0-work4 the
`_ENV` thing) but rather set to the environment of the module's
implementation.  Given that I don't like mixing a module's public
table with its private namespace (e.g. package.seeall or even to some
extent `_ENV = module(...)`), or at least it's slightly cumbersome
(package.clean), and given that 5.2.0-work4 makes an equivalent
variable (_ENV) available anyway if you choose the `_ENV =
module(...)` style, and even 5.1 provided getfenv(1), I don't see much
point.

_PACKAGE is contained in _NAME, and _NAME is available if needed to a
module's implementation via `...`.  The case usually cited is to
lookup related modules if modules are allowed to be renamable.  I
don't see a need to expose _NAME via a module's public table though,
but in worst case you could search package.loaded to map any module to
its module name.  Something that I think has been requested is mapping
a module to its file name it was loaded from, though you can infer
that from _NAME if package.path and sometimes CWD if unchanged over
time or via debug.getinfo on a member function.

Some also define something like _VERSION (a la Perl).

On #3, I recall it not being flexible enough when I've tried to do
things with it.  It provides a hook into when a module is first
created but does not provide a hook into after the module's loader is
run.  In the case of package.clean, it involves some ugly hack with
setfenv:

  -- CosminApreutesei's 2009oct version,
http://lua-users.org/wiki/ModuleDefinition
  local CLEAN_ENV = { pairs = pairs, unpack = unpack, ... }
  local P_meta = {__index = CLEAN_ENV}
  function package.clean(M)
    local P = setmetatable({}, P_meta)
    setfenv(3, setmetatable({}, {__index = P, __newindex =
function(t,k,v) M[k]=v; P[k]=v; end}))
  end

>>> (4) set the _ENV of the caller to be the module (lauxlib.set_env).
>>
>> Not OK, the move to _ENV is to give back to closure the control of
>> their global variables. If the module wants to change its _ENV, it
>> should do so explicitly :
>>
>> _ENV = module(... or 'test', package.seeall)
>
> I would argue that this is precisely a feature belonging in module(): declare a module and set
> its environment, all at once. In my point of view, this is a feature, not a bug, irrespectively
> of details implementation (setfenv vs. _ENV).

I see the desire for that, though I've come to the opinion that
environments (_ENV) are not that useful in module definition [1-3].
That is for me the question is more of whether `local M = {} .....
return M` should somehow be made more implicit rather than `_ENV =`
being implicit.

[1] http://lua-users.org/lists/lua-l/2010-08/msg00148.html
[2] http://lua-users.org/lists/lua-l/2010-08/msg00213.html - "perhaps
the answer to #2 is no"
[3] http://lua-users.org/lists/lua-l/2010-08/msg00236.html