modules, require, magic

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
160 messages Options
1 ... 345678
Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Hisham Muhammad
On Thu, Oct 20, 2011 at 3:03 PM, Roberto Ierusalimschy
<[hidden email]> wrote:
>> > 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().
>
> Maybe I am missing something, but I got the impression that, with
> loader5 (as posted to the list), I get an empty environment if I do not
> call 'module'.

Indeed; and at a first glance I don't seem to be able to fix this
without resorting to the debug library. In any case, at this point I
assume that "_ENV = module('name')" would be the preferred direction
to go for a possible Lua 5.2 version of module().

>  local function loader(name, modpath)
>    local mod, env = {}, {}
>   env.module = function (name)  ...   -- not called
>   ...
>   local ret = assert(load(source, modpath, 'bt', env))(name)
>   ...
>  end
>
> Moreover, it seems that loader5 has some other drawbacks. (It needs to
> read the whole module as a string; all accesses to globals go all the
> time through function calls.)

With the module() + package.seebase variation suggested at [1] I think
the only remaining drawback would be that all accesses to globals go
all the time through function calls when using package.seebase.

Myself, I could live with that (resorting to the ugly "local
print=print" idiom if performance was really needed); I'd rather take
this hit than the other issues of package.seeall (in which globals
already go through a metamethod anyway, no?), or having to localize
every needed global from the base library.

Having said that, if the standard library remained the same as the one
in Lua 5.1, I'd probably keep using package.seeall instead of rolling
my own package.seebase, for the sake of sticking to standard idioms.

[1] http://article.gmane.org/gmane.comp.lang.lua.general/84444

-- Hisham
http://hisham.hm/ - http://luarocks.org/

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

David Manura
In reply to this post by Hisham Muhammad
On Wed, Oct 19, 2011 at 1:25 AM, Hisham <[hidden email]> wrote:
> Discussing this offlist with Fabio he also mentioned another benefit
> of module()-style modules: that one can easily inspect the code
> mechanically for global declarations and infer what's exported, while
> module()-less-modules make this kind of static analysis a lot more fragile.

LuaInspect's experience has actually been the opposite.  It can infer
from first principles that the following chunk returns a table
containing a field "baz" having a function value, even though the
coding style is mildly pathological:

local abc = (function() return {} end)()
local x = "b"
if true then
  foo()
  abc[x  .. "az"] = function() foo() end
end
abc['y' .. math.random(10)] = 1
local function gg()
  print 'a'
  return x and abc
end
return gg()

This is done without executing "print 'a'" and without knowing the
definition of "foo" or the return value of math.random(10).  In short
it makes the following inferences, which a human can likewise easily
do:

  - Some values are constant folded.
  - Some locals are inferred to be constant (barring extraordinary
things with the debug library inside foo).
  - Return values or types of some functions are inferred.

Now with the module function, at least in its 5.1 form, LuaInspect
doesn't even attempt to interpret it statically but rather falls back
to a dynamic evaluation in the Lua VM.  Environments with metatables
are more complicated to analyze by a human as well as computer.  Yes,
you could (or even should) feed the analyzer some preconceived
semantics of standard functions like module/package.seeall and assume
nothing tricky like redefinition of these functions has been done, but
this is not derived from first principles. Incidentally, LuaInspect is
fed preconceived static semantics for require, and it assumes that a
global with that name is that function (require is not a keyword in
Lua).  Fortunately, unlike in an optimizing compiler, it's not
catastrophic but rather is helpful for LuaInspect to make such
assumptions.

Yes, Lua 5.2.0-beta's restrictions on environments can also simplify
static analysis:

    _ENV = {}  -- We know lexically that this environment has no
metatable funny business.
    x = 1
    f()  -- Unlike in 5.1, functions are not normally permitted to
alter the caller's environment.
    return x  -- Therefore, we can infer this will always return 1.

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

David Manura
In reply to this post by Tony Finch
On Wed, Oct 19, 2011 at 12:52 PM, Tony Finch <[hidden email]> wrote:
> Hisham <[hidden email]> wrote:
>> But having to write "module.bar" (or "M.bar", or "_M.bar"...) in every
>> use of module functions within the module is cumbersome.
> Muddling up the global and module namespaces is not clean.

Returning to an example based on what I posted before [1]:

  _ENV = module(...)
  local tostring = tostring
  local baz = require "baz"
  .....
  local test
  function foo(...) ..... end
  Bar = class('Bar', function(_ENV)
      .....
      function tostring(self)  -- NOTE! actually defines a local function
        return foo(self.x)  -- NOTE! does not necessarily access foo
in parent _ENV scope
      end
  end)
  function test() ..... end  -- NOTE! this is a forward declared local
(but resembles a global)

Here we attempt _ENV tricks for both modules and classes, and I'm
skeptical that the scoping meshes well.

[1] http://lua-users.org/lists/lua-l/2010-07/msg00224.html

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

steve donovan
In reply to this post by Hisham Muhammad
On Thu, Oct 20, 2011 at 10:37 PM, Hisham <[hidden email]> wrote:
> With the module() + package.seebase variation suggested at [1] I think
> the only remaining drawback would be that all accesses to globals go
> all the time through function calls when using package.seebase.

That's why my solution suggested that the environment has a straight
__index=lua_libs, and the actual module is a copy of the environment
(whether constructed implicitly through __newindex or explicitly
through a table copy).

So, yes, there's still a little indirection, but not involving a function call.

It's true that _any_ module gets a fresh environment, although this
might be seen as a feature (strictly reducing use of global namespace)

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: syntactic sugar for imports and exports

Xavier Wang
In reply to this post by Tony Finch
I love this idea!

2011/10/20 Tony Finch <[hidden email]>:

> Further thoughts on the use+mention problem, where we have to repeat a
> name to use it as a variable and to mention it as a table index or
> function argument. The main examples are:
>
>  local name = name            -- keep name in scope after altering _ENV
>  local name = module.name     -- import unqualified name from module
>  local name = require "name"  -- module linkage
>  { name = name }              -- export variable into table
>
> The usual proposal to improve the first two is as follows, but I'm trying
> to find a more general solution.
>
>  local name in _ENV
>  local name in module
>
> I call the first three "projection" from a table or function into
> variables and the last one "injection" from variables into a table.
>
> It seems to be helpful to think of both projection and injection as
> special kinds of assignment. This emphasizes their duality, and it
> suggests a better syntax for injection.
>
> So the syntax for projection might be like
>
>  foo, bar, zig <- tbl
>
> where "foo, bar, zig" is a list of variable names and "tbl" is an
> expresion. The "<-" is pronounced "from" as in "assigned from" or
> "imported from". This is equivalent to
>
>  foo, bar, zig = tbl.foo, tbl.bar, tbl.zig
>
> except that tbl is evaluated once. A projection statement starting with
> "local" has the obvious translation:
>
>  local foo, bar, zig <- tbl
>  local foo, bar, zig = tbl.foo, tbl.bar, tbl.zig
>
> Injection might be like
>
>  tbl -< foo, bar, zig
>
> which is equivalent to
>
>  tbl.foo, tbl.bar, tbl.zig = foo, bar, zig
>
> with the same conditions as before. Injection needs a different operator
> so you can tell the difference between "x <- y" and "y -< x". The "-<"
> symbol is the syringe operator.
>
> I think on balance it doesn't make sense to support projecting from
> functions directly. This avoids muddling the concepts of indexing and
> calling, but you can still use the __index metamethod if you want. For
> example,
>
>  -- syntactic sugar for require
>
>  library = setmetatable(package.loaded, {
>              __index = function (_, name)
>                          return require(name)
>                        end
>            })
>
>  -- get math and io modules from the library
>
>  local math, io <- library
>
> Tony.
> --
> f.anthony.n.finch  <[hidden email]>  http://dotat.at/
> Dover, Wight, Portland, Plymouth: Northwest 4 or 5, increasing 6 at times,
> backing west 3 later. Slight or moderate, occasionally rough in Plymouth at
> first. Showers. Good.
>
>

Reply | Threaded
Open this post in threaded view
|

Re: syntactic sugar for imports and exports

steve donovan
In reply to this post by Tony Finch
On Thu, Oct 20, 2011 at 12:40 AM, Tony Finch <[hidden email]> wrote:
>  local foo, bar, zig <- tbl
>  local foo, bar, zig = tbl.foo, tbl.bar, tbl.zig

Very nice notation!

>  tbl -< foo, bar, zig

The 'syringe operator' is great naming.

I suppose the chief obstacle to adoption is that this is fairly
specialized sugar, and not keyword-driven.

Another option for injection-syntax for modules would be something like this:

return { @foo, @bar, @zig }

or

return { foo=@, bar=@, zig=@ }

 (becomes return { foo = foo, bar = bar, zig = zig } which is common
also in other contexts)

However, weird sigils have usually been frowned upon, because of the
old fear-of-Perl.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

James Graves-2
In reply to this post by Hisham Muhammad
"Hisham" <[hidden email]> wrote:
> With the module() + package.seebase variation suggested at [1] I think
> the only remaining drawback would be that all accesses to globals go
> all the time through function calls when using package.seebase.

Can we just do this instead for seebase?

function package.seebase(mod)
   local env = {}
   setmetatable(env,
        { __index = setmetatable(mod, {__index = lua_libs}),
          __newindex = mod })
    return env
end

More indirection, but no function call. Since we're already copying
package.loaded._G can we just lazily cache those in the mod table too?

-------------------------------

Other people have been complaining about the module discussion on the
list recently, but I think it has been productive too.

I think we may be close to a solution that will have broad approval.

James Graves

Reply | Threaded
Open this post in threaded view
|

Re: syntactic sugar for imports and exports

Tony Finch
In reply to this post by steve donovan
steve donovan <[hidden email]> wrote:
>
> I suppose the chief obstacle to adoption is that this is fairly
> specialized sugar, and not keyword-driven.

Yes.

For fans of hyperglycemic syntax, what I'm really doing is skating
on the edge of full blown functional-style pattern matching and table
comprehensions :-)

> Another option for injection-syntax for modules would be something like this:
> return { @foo, @bar, @zig }
> or
> return { foo=@, bar=@, zig=@ }

I was thinking { = foo, = bar }

Tony.
--
f.anthony.n.finch  <[hidden email]>  http://dotat.at/
South Utsire, Forties: Southwesterly 5 to 7, perhaps gale 8 later. Rough.
Occasional rain. Moderate or good.

Reply | Threaded
Open this post in threaded view
|

Re: syntactic sugar for imports and exports

Xavier Wang

i prefer "in" keywords....
在 2011-10-21 晚上11:49,"Tony Finch" <[hidden email]>写道:
>
> steve donovan <[hidden email]> wrote:
> >
> > I suppose the chief obstacle to adoption is that this is fairly
> > specialized sugar, and not keyword-driven.
>
> Yes.
>
> For fans of hyperglycemic syntax, what I'm really doing is skating
> on the edge of full blown functional-style pattern matching and table
> comprehensions :-)
>
> > Another option for injection-syntax for modules would be something like this:
> >       return { @foo, @bar, @zig }
> > or
> >       return { foo=@, bar=@, zig=@ }
>
> I was thinking { = foo, = bar }
>
> Tony.
> --
> f.anthony.n.finch  <[hidden email]>  http://dotat.at/
> South Utsire, Forties: Southwesterly 5 to 7, perhaps gale 8 later. Rough.
> Occasional rain. Moderate or good.
>

Reply | Threaded
Open this post in threaded view
|

Re: syntactic sugar for imports and exports

Jerome Vuarand
In reply to this post by Tony Finch
2011/10/20 Tony Finch <[hidden email]>:

> [...]
>
>  -- syntactic sugar for require
>
>  library = setmetatable(package.loaded, {
>              __index = function (_, name)
>                          return require(name)
>                        end
>            })
>
>  -- get math and io modules from the library
>
>  local math, io <- library

That proposal is smart, and very refreshing. Whatever the outcome, I
believe that's good food for thoughts :-)

As I personnally prefer keywords to symbols (in the context of Lua at
least), I'd rather have "from" be used instead of "<-" (since that's
how you read, why not write it that way?).

Injection on the other hand sounds less useful, and at the same time I
can't think of a good keyword to put in the place of your syringe
operator. A very bad one would be "sucks" (I'm not a native english
speaker and I can't find a better synonym):

   tbl -< foo, bar, zig

becomes

   tbl sucks foo, bar, zig -- from the globals

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Roberto Ierusalimschy
In reply to this post by David Manura
> On Wed, Oct 19, 2011 at 1:25 AM, Hisham <[hidden email]> wrote:
> > Discussing this offlist with Fabio he also mentioned another benefit
> > of module()-style modules: that one can easily inspect the code
> > mechanically for global declarations and infer what's exported, while
> > module()-less-modules make this kind of static analysis a lot more fragile.
>
> LuaInspect's experience has actually been the opposite. [...]

This is quite interesting. It turns upside down a strong argument in
favor of 'module'.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Sam Roberts
In reply to this post by Mark Hamburg
On Mon, Oct 17, 2011 at 11:37 PM, Mark Hamburg <[hidden email]> wrote:
> Let's run through what module does.
[snip]
> Obviously others differ, but I think it would be useful to hear which of these behaviors is deemed so valuable that people are fighting for it.

I read the anti-module wiki page, was convinced, drank the koolaid,
and started not using it

4 or 5 modules in I realized I was reimplementing the module()
function myself, which was lame, and I regret it. We've been switching
over to module() and enjoying it a bunch.

I'd say the single biggest problem with losing module is that we have
to port everything to 5.2, and do it in a way that also works for 5.1
(which will be here a long time).

Its a PITA, for pretty marginal benefit. So, its not primarily about
whether a no-module() world is marginally better, its that just when
we're starting to collect some lua modules, they all stop working!

And a number of the people coming out against module use it
extensively in their own code, its hard to understand them hating it
that much.

If 5.2 at the very least had a module(), where you could do

  local _ENV = module(..., package.seeall)

and a second argument to require so you could to

  require("some.mod", package.register)
  assert(some.mod)
or
  local mod = require"some.mod"

the situation would be better. For the common idiom of constructing
modules in 5.2 to immediately require advanced metatable knowledge,
seems unfortunate to me.

  local _ENV = setmetatable({}, {__index=_G})
  function foo() end
  return _ENV

> 1. It handles constructing module tables including the fields _NAME, _M, and _PACKAGE. This is useful if one cares about these fields, but I note that they don't appear in the pre-defined modules like table and string.

I use this in constructing modules from multiple files:

  zbee/
     init.lua -- this will require(_NAME..".app"), etc.
     app.lua
     link.lua

The module(...) doesn't self doc, but it follows DRY, don't repeat yourself.

It allows me to svn mv zbee to protocol/zbee, not change any of its
code, and the module has a different name (protocol.zbee). Useful also
because the test code in the zbee/ subdir can require the files
directly, and different applications using the module can refer to it
by different names, depending on how their package.path is set up.

> 2. It handles constructing submodules. I might question whether it makes sense to have socket.http available when socket is potentially just a stub table, but that's a more complicated matter.

I find hierarchical namespacing useful. I like that we can have
fw/pump/tcp.lua, and that  tcp is not the same as
protocol.tcp.lua. And doing

  local fwpumptcp = require"fw.pump.tcp"
  local protocoltcp = require"protocol.tcp"

strikes me as awkward and silly.

> 4. It adds the module to the global namespace. This, in my opinion, is a bad thing because it creates hidden dependencies -- i.e., code can use a module that it never required simply because some other code required it earlier and it became available in the global namespace.

This can bite you, but it can be a boon. In particular, notice that we
don't have to do a require"io" or require"table" before using the io
or table modules.... (with the standard lua interpreter). OMG! Hidden
dependencies! In a non-standard interp, like a lua_State that hasn't
had register all called on it, your code won't work... but I've
never seen any lua code call require"table"....

Everybody who _REALLY_ thinks having module names be global, I'd say
you should be lobbying for all the standard modules to be removed from
the global namespace. I'd be vehemently opposed, of course, but at
least you'd be consistent!

One thing I do agree with, is that whether the modules are injected
globally in nested tables should be a parameter to require, not a
side-effect of module.

But on the other hand, whats the global table for, if not for putting
modules? Surely you don't put your __variables__ in there, do you?

function that()
  -- BAD, BAD, BAD!
  i = 4
  j = 9
  return i + j
end

Our code doesn't use the global debug, but we do require our own
frameworks, and we want them globally available, so testcase plugins
can

  require"tcp.plugin"

and everything they might want is there. I don't want to start our
plugins with 18 lines of

  local blah = require"some.blah"

statements.

> 5. It mucks with the environment to make it "easy" to export functions. But then to compensate for this, it offers package.seeall which results in a module that reveals a lot of globals in its table which have nothing to do with the module -- i.e., it pollutes the API for the module.

I've never seen this be a problem in practice (not saying that it
can't be, of course). In particular, even python (which some people
seem to wish lua was more like :-(), and which makes it
extraordinarily hard to import anything so its global across all
modules, allows this so-called "pollution":

    -- bar.py
    import logging # logging is now available as bar.logging

The setting of the modules env to the module table doesn't just make
it "easy" to export functions, it makes it easy to not care whether
the functions is exported or not within the module;

module(....)

local function do_that() end

... lots of code that uses do_that()
----

When I decide I want do_that() exported, because its super useful, I
just remove the local, and its all good.

Contrast with the simplest of the many 5.2 module definition techniques:

local _M = {}

local function do_that() end
 ---[[ when this becomes
  function _M.do_that() end
all the code below will break, so then I guess we define a local
alias, for backwards compat?
 local do_that = _M.do_that -- LAME!
or we do a search and replace on the whole file, just because we now
export the function as part of the module?
]]

... lost of code that uses do that
return _M
------


Cheers,
Sam

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Roberto Ierusalimschy
In reply to this post by Hisham Muhammad
> 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

With the use being "_ENV = module(...)", we actually do not need the
vararg stuff. We can simply write the modifier explicitly; for instance:

   _ENV = seebase(module(...))


BTW, something that seems to be going unnoticed is that, in 5.2 beta,
require calls the loader with two arguments, instead of only one:

  http://www.lua.org/work/doc/manual.html#pdf-require
  [...]
  Once a loader is found, require calls the loader with two arguments:
  modname and an extra value dependent on how it got the loader. (If the
  loader came from a file, this extra value is the file name.)

Something like "module(..., seeall)" would throw away that second
argument.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Petite Abeille
In reply to this post by Roberto Ierusalimschy

On Oct 21, 2011, at 8:43 PM, Roberto Ierusalimschy wrote:

>> On Wed, Oct 19, 2011 at 1:25 AM, Hisham <[hidden email]> wrote:
>>> Discussing this offlist with Fabio he also mentioned another benefit
>>> of module()-style modules: that one can easily inspect the code
>>> mechanically for global declarations and infer what's exported, while
>>> module()-less-modules make this kind of static analysis a lot more fragile.
>>
>> LuaInspect's experience has actually been the opposite. [...]
>
> This is quite interesting. It turns upside down a strong argument in
> favor of 'module'.

Lets not get too distracted by Mr. Manura esoteric endeavors as module, in and by itself, does not impede, nor greatly facilitate, "static analysis" of anything as dynamic as Lua.

What module does provide is a simple, common, and consistent way to define, well, modules. Why don't we leave it at that?





Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Luiz Henrique de Figueiredo
In reply to this post by Sam Roberts
> we don't have to do a require"io" or require"table" before using them

But you *can* do the requires. So, if you feel better using them, by all
means do it.

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Petite Abeille

On Oct 21, 2011, at 9:54 PM, Luiz Henrique de Figueiredo wrote:

>> we don't have to do a require"io" or require"table" before using them
>
> But you *can* do the requires. So, if you feel better using them, by all
> means do it.

Not only will it make you feel better, but if you are in a closed environment (e.g. a module :), you have too. Which is a good thing :)


Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Philipp Janda
In reply to this post by Sam Roberts
On 21.10.2011 20:49, Sam Roberts wrote:
>
 > [...]
>
> I'd say the single biggest problem with losing module is that we have
> to port everything to 5.2, and do it in a way that also works for 5.1
> (which will be here a long time).

Just use the proposed module-less module system -- it will work for Lua
5.1 and 5.2 (no matter what is decided for the future of "module")!

>
> [...]
>
> For the common idiom of constructing
> modules in 5.2 to immediately require advanced metatable knowledge,
> seems unfortunate to me.
>
>    local _ENV = setmetatable({}, {__index=_G})
>    function foo() end
>    return _ENV

The proposed common idiom for 5.2 is:
local M = {}
function M.f() end
return M

No metatable or environment knowledge required at all for completely
understanding what is happening!

>
>> 1. It handles constructing module tables including the fields _NAME, _M, and _PACKAGE. This is useful if one cares about these fields, but I note that they don't appear in the pre-defined modules like table and string.
>
> I use this in constructing modules from multiple files:
>
>    zbee/
>       init.lua -- this will require(_NAME..".app"), etc.

                  -- that would be require( (...)..".app"), now.

>       app.lua
>       link.lua
>
 > [...]

>
>> 2. It handles constructing submodules. I might question whether it makes sense to have socket.http available when socket is potentially just a stub table, but that's a more complicated matter.
>
> I find hierarchical namespacing useful. I like that we can have
> fw/pump/tcp.lua, and that  tcp is not the same as
> protocol.tcp.lua. And doing
>
>    local fwpumptcp = require"fw.pump.tcp"
>    local protocoltcp = require"protocol.tcp"
>
> strikes me as awkward and silly.

You could also write:
local protocol = { tcp = require"protocol.tcp" }

The point is: The user of the module has the choice!

>
> [...]
>
> Our code doesn't use the global debug, but we do require our own
> frameworks, and we want them globally available, so testcase plugins
> can
>
>    require"tcp.plugin"
>
> and everything they might want is there. I don't want to start our
> plugins with 18 lines of
>
>    local blah = require"some.blah"
>
> statements.

$ cat > allmymodules.lua
return {
   tcp = require( "tcp.plugin" ),
   udp = require( "udp.plugin" ),
   raw = require( "raw.plugin" ),
   test = require( "test" ),
   other = require( "my.other.module" ),
   -- ...
}
^D

... which reduces your 18 lines to one line as it is now.

>
> [...]
>
> Cheers,
> Sam
>

Philipp



Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Sam Roberts
On Fri, Oct 21, 2011 at 3:59 PM, Philipp Janda <[hidden email]> wrote:

> On 21.10.2011 20:49, Sam Roberts wrote:
>>
>> [...]
>>
>> I'd say the single biggest problem with losing module is that we have
>> to port everything to 5.2, and do it in a way that also works for 5.1
>> (which will be here a long time).
>
> Just use the proposed module-less module system -- it will work for Lua 5.1
> and 5.2 (no matter what is decided for the future of "module")!

You say "just use", but you mean is "rewrite everything".

You seem to be making the point that it is possible to write modules
in 5.2, but I don't dispute that, not does anyone else.

I just don't want to rewrite everything for dubious advantage.

> The proposed common idiom for 5.2 is:
> local M = {}
> function M.f() end

Like prepending M. to the start of every function defined in my modules.

> You could also write:
> local protocol = { tcp = require"protocol.tcp" }

> The point is: The user of the module has the choice!

A module has one definition, and many users, your proposal means
modifying every use of the module to construct the namespace implicit
in the module name. Of course, instead, I'd rewrite require to do
this.

Sam

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Sam Roberts
In reply to this post by Luiz Henrique de Figueiredo
On Fri, Oct 21, 2011 at 12:54 PM, Luiz Henrique de Figueiredo
<[hidden email]> wrote:
>> we don't have to do a require"io" or require"table" before using them
>
> But you *can* do the requires. So, if you feel better using them, by all
> means do it.

Writing code that does nothing doesn't make me feel better.

Its a null OP, nobody does it, and in the rare lua environments where
it actually did load the table module, it would cause it to be
injected into the global namespace, would it not?

So, the standard lua modules display the "pollution" problem that the
5.1 module() function is being criticized for.

If you don't like modules to be implicitly created as globals by
require, then in lua 5.2 this should be true:

assert(not string)
local s = require"string"
assert(not string)
assert(s.gsub)

Cheers,
Sam

Reply | Threaded
Open this post in threaded view
|

Re: modules, require, magic

Josh Simmons
In reply to this post by Sam Roberts
On Sat, Oct 22, 2011 at 10:07 AM, Sam Roberts <[hidden email]> wrote:

> On Fri, Oct 21, 2011 at 3:59 PM, Philipp Janda <[hidden email]> wrote:
>> On 21.10.2011 20:49, Sam Roberts wrote:
>>>
>>> [...]
>>>
>>> I'd say the single biggest problem with losing module is that we have
>>> to port everything to 5.2, and do it in a way that also works for 5.1
>>> (which will be here a long time).
>>
>> Just use the proposed module-less module system -- it will work for Lua 5.1
>> and 5.2 (no matter what is decided for the future of "module")!
>
> You say "just use", but you mean is "rewrite everything".
>
> You seem to be making the point that it is possible to write modules
> in 5.2, but I don't dispute that, not does anyone else.
>
> I just don't want to rewrite everything for dubious advantage.
>

You say rewrite but you mean s/^function /function M./c

>> The proposed common idiom for 5.2 is:
>> local M = {}
>> function M.f() end
>
> Like prepending M. to the start of every function defined in my modules.
>

Yes the onerous task of adding two extra letters is similar than that
of designing a reusable API.

>> You could also write:
>> local protocol = { tcp = require"protocol.tcp" }
>
>> The point is: The user of the module has the choice!
>
> A module has one definition, and many users, your proposal means
> modifying every use of the module to construct the namespace implicit
> in the module name. Of course, instead, I'd rewrite require to do
> this.
>
> Sam
>

You're completely insane if you'd monkey patch standard functions for
a small convenience such as this. How many of your modules have such
important nesting?

1 ... 345678