lua-users home
lua-l archive

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

Diego Nehab escribió:

> Whatever we do, I prefer that each library creates its own table.
> Having the library receive a table to fill doesn't seem to be so
> advantageous. Besides, libraries written in Lua would require deeper
> modifications.

The advantage is that the library can be imported into another module
before it has been created. If you have two libraries which refer to
each other, and you don't want to put them into the "global" namespace
(which might not exist in any meaningful sense anyway), then there is
really no other way of doing it that I can see.

I don't see any deep modifications here. I have some chunk which
looks like this:

local module = {}
function module:foo() ... end
function module:bar() ... end
return module

I change it to this:

return function(module)
  function module:foo() ... end
  function module:bar() ... end
  return module

That is one line changed at the beginning and one "end" added at the end.
Any internal reference to module:foo will be the same in both chunks.
Am I missing something?

Let me reiterate that I am not proposing this because of global namespace
pollution, although I don't like having a lot of stuff in globals. I am
proposing it because it makes sandboxes easier, and because it lets me
load two implementations/versions of the same module at the same time.

Still, not having to use long.complicated.module.names all the time is a
big plus: I like module systems like Dylan's for exactly that reason.
The module namespace can be hierarchical, but my references to libraries
are simply what I chose to use in my little snippet of code:

  local mime = require "com.nehab.diego.mime"

  local foo = mime.decode(...) -- or whatever

I'm not sure I understand the issue about mime.lua and mime.dll. It seems
they are both needed, mime.lua won't work without mime.dll. So it is logical
(to me) to require the .dll and have it include mime.lua as a string
constant. That makes for one less file to have to worry about when installing
the mime library. But I suppose not everyone would agree with that: it does
make editing the lua part of the mime module more work. (Nothing that a
makefile couldn't fix, though.)

I can't resist pointing out that the convention of handing a module creation
function a table rather than having it make its own is ideal in the case that
you want to combine C and Lua functions in the same module table: one of them
can call the other one's instantiation function with the table. So there's
another application for the paradigm.

In any event, you could use hierarchical naming just as easily as two require
functions; these two lines are pretty similar:

  requirelib "mime"
  require "mime.c"

Finally, I think the code I presented demonstrates how easy it is to handle
static vs. dynamic libraries using this approach. I know it was a lot of
uncommented code, and I threw it together without making sure that it all
works :(, but it's only a couple of pages in the end.

If you look closely at that code, you will see that it keeps the module
instantiation function as the value in a weak-keyed table whose key is
the module table itself; the module table, in turn, is kept in the module
cache. This means that a module once imported into a cache will not get
garbage collected until the cache is no longer referenced. If these caches
correspond to sandboxes (which was my intention), that will be precisely
correct, as far as I can see.

There is no issue with static libraries being accidentally unloaded
because the static library is never loaded with loadlib and thus does not
have an associated library handle. And all of this without even Edgar's
quite clever upvalue mod.