lua-users home
lua-l archive

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


On Mon, Oct 17, 2011 at 3:00 PM, Sam Roberts <vieuxtech@gmail.com> wrote:
> On Mon, Oct 17, 2011 at 9:07 AM, Petite Abeille
> <petite.abeille@gmail.com> wrote:
>>
>> On Oct 17, 2011, at 4:28 PM, Javier Guerra Giraldez wrote:
>>
>>> module() is gone,
>>
>> It's not gone. It's alive and kicking in 5.1.
>>
>> 5.2 is not released. In 5.2, it might  be deprecated. Which means it's going to be there for years to come.
>>
>>> the replacement is far simpler,
>>
>> Bollox :)
>>
>>> I really don't get why to keep discussing about it.
>
> Because module and require worked fine, and provided a common way to
> implement modules.
>
> Now we are trying to support two ways, check out this code at about line 60:
>
> https://github.com/dcurrie/lunit/blob/master/lunit.lua
>
>> Well, is there a party line we have to toe? Or is it acceptable to voice discontent?
>
> Petite, probably its not useful to voice discontent... though I share
> your pain, and I'm going to voice mine, too!
>
> The occaisonal suggestion that lua programmers widely disliked
> module() is pretty galling, and I'm tempted to deface that wiki page
> people keep pointing to like it represents some kind of consensus
> opinion, when its only the opinion of a few.

Yes, you are not alone. I agree that it is not a consensus opinion.

Even though that "Lua Module Function Critiqued" page (mostly written
by David Manura?) is sponsored by some influential members of the Lua
community (David, Mike Pall, etc.) and the points written there are
indeed valid, I think that those problems are often overrated, and we
shouldn't forget about the good aspects of module() as well.

Let's start by remembering the circumstances that brought us module().
For long, Lua has lacked behind other languages in its ability to
write reusable, modular code. First we got require() in Lua 5.0, which
allowed us to abstract away the some of the filesystem specifics in
scripts (but lacking, AFAIR, submodules). require() didn't enforce the
return of the module, so some packages would just add to the global
namespace, some would return a table, etc.

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. Yes, the implementation has the pitfalls listed in the
"Critiqued" page. Yes, having to add something like "package.seeall"
to get something similar to what would be the default behavior in most
other languages is unfortunate. But it's really nice to be able to
open a source file and read something like " module('foo.bar.baz') "
on top, which gives a clear indication of how this module should be
loaded.

I've always seen the evolution of the Lua modules system (require in
Lua 5.0, module in Lua 5.1, compat-5.1 for Lua 5.0) as an attempt to
provide some standardization in order to promote code interoperability
and reusability. As Roberto says in PiL:

"Usually, Lua does not set policies. Instead, Lua provides mechanisms
that are powerful enough for groups of developers to implement the
policies that best suit them. However, this approach does not work
well for modules. One of the main goals of a module system is to allow
different groups to share code. The lack of a common policy impedes
this sharing."

The implementation of module() in Lua 5.1 may not be ideal, but
requiring users to learn about _ENV in order to write a reusable
module is, in my opinion, worse. Yes, it's a mechanism that's powerful
enough to get the job done, but don't we risk to go back to the Lua
5.0 days in terms of code sharing?

My opinion is that modules are important enough so that there should
be a "blessed" way of writing modules, and preferrably a somewhat
obvious one. There has to be a policy.

Looking at modules that are contributed to LuaRocks, I see that
module() is popular among developers and promotes a clean, uniform way
of describing modules, whereas among those who don't use it you see
all styles of coding. It's nice to look at module() on top and see
that the file was designed to be require()'d, that it won't pollute
the global namespace beyond the name of the module (yes, would be even
nicer if it didn't pollute the environment at all), that you can
assign the return of require() to a local. It's important to have
those guarantees when writing code with reusable components.

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 (along
the lines of ":" being justifiable for the sake of OOP). (Perhaps even
the "in ... end" that was once proposed for environments? (But please,
let's stick to discussing the merits/problems of a canonical module
construct, rather than diving in yet another
let's-discuss-syntax-details thread)).

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