Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
Hi all!

[Warning: long post ahead]

I realized the discussion on the originating thread was hitting the
limits of my Lua knowledge, so I'm starting a new thread to avoid adding
noise to it with "newbie stuff".

All the discussions about environments, globals and modules have
confused me a bit (especially after rereading what's in the WIKI about it).
Therefore I'd like to receive comments on my current practice when it
comes to write a new module (nothing original below, just a concoction
of what I read and learned about modules from the list and WIKI in the
last months).

What I'm trying to assess here is whether the following approach (very
basic, avoiding as much "magic" and "debug" library support as possible)
is reasonably foolproof and safe.

Note that it is a rather "verbose" solution, and that's an intended
trade-off for (hopefully) better encapsulation, less "baggage", and good
performance (thanks to heavy use of locals), all under an "avoid globals
like The Plague" approach.

Are there pitfalls/caveats in this approach (under the assumption that
the debug library is not used to tamper with the "module system")?
If every module in the system had this structure, would I be safe from
side effects from other modules/components/scripts (directly or
indirectly loaded, either with "require" or with "loadXXX" functions)?
Am I missing something or assuming too much?

Any comments appreciated!

TIA
--- Lorenzo



Currently my modules have the following structure (Lua 5.1.4 assumed):


-- mymodule.lua (placed in directory a\b\c on Lua's search path)

-- if needed to locate other components:
local module_dir = debug.getinfo(1, "S").source:match[[^@[^\/]-$]] and
"." or debug.getinfo(1, "S").source:match[[^@?(.*)[\/][^\/]-$]]

local print = print
local setfenv = setfenv
local setmetatable = setmetatable
local table_concat = table.concat
-- ... other "localization" of needed standard globals


local M_ENV = {} -- just a sink for unintended global accesses, not used
internally
setfenv(1, M_ENV)
local M = {} -- module table (will be "exported" to outer world)

-- "requiring" of external modules goes here:
local extmod = require "org.lua.morecoolstuff"

-- example of private data and function:
local x = 12
local function helper() --[[ do stuff ]] end


-- example of function to be exported:
local function M_MyCoolFunc(a,b,c)
  --[[ do stuff ]]
end
-- "declare" M_MyCoolFunc to be exported
M.MyCoolFunc = M_MyCoolFunc


-- instead of simply "return M", so what gets
-- into "package.loaded" is read-only:

return setmetatable({}, { __index = M, __metatable = "locked",
   __newindex = function()
     error "attempt to write to read-only table"
   end })
-- end mymodule.lua

-- module usage:

local mymod = require "a.b.c.mymodule" --> module's "namespace" table

mymod.MyCoolFunc("Hep!", 1, 2)

Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Matthias Kluwe
Hi!

2010/8/17 Lorenzo Donati <[hidden email]>:

> [...]
>
> Note that it is a rather "verbose" solution, and that's an intended
> trade-off for (hopefully) better encapsulation, less "baggage", and good
> performance (thanks to heavy use of locals), all under an "avoid globals
> like The Plague" approach.
>
> Are there pitfalls/caveats in this approach (under the assumption that the
> debug library is not used to tamper with the "module system")?
> If every module in the system had this structure, would I be safe from side
> effects from other modules/components/scripts (directly or indirectly
> loaded, either with "require" or with "loadXXX" functions)? Am I missing
> something or assuming too much?

I don't think you approach is verbose. Personally, I use the "simply
return a local table from a 'module'" by myself and have not felt the
need to do something more sophisticated yet. I even do without your
"read-only" safety measure, thus my solution is even more basic.

Using Lua as an extension language, the main benefit of this maybe
most basic approach is that it is explainable to inexperienced and
temporary co-workers.

Regards,
Matthias
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Sean Conner
In reply to this post by Lorenzo Donati-2
It was thus said that the Great Lorenzo Donati once stated:

>
> I realized the discussion on the originating thread was hitting the
> limits of my Lua knowledge, so I'm starting a new thread to avoid adding
> noise to it with "newbie stuff".
>
> All the discussions about environments, globals and modules have
> confused me a bit (especially after rereading what's in the WIKI about it).
> Therefore I'd like to receive comments on my current practice when it
> comes to write a new module (nothing original below, just a concoction
> of what I read and learned about modules from the list and WIKI in the
> last months).

  The problem (as I see it) comes down to poluting the global namespace.
module() basically loads some code and returns it in a new global table
(plus maybe some magic).  I know that when I first started playing around
with Lua modules it wasn't all that intuitive to me.

  Just in the past few days I came up with the following bit of code:

-- **********************************************************************

nmodules       = {}
nmodules.lpath = { "./?.lua" }
nmodules.cache = {}

-- **********************************************************************

function loadtoenv(fname)
  local env   = setmetatable({} , { __index = _G } )
  local f,err = loadfile(fname)

  if f == nil then
    return nil,nil,err
  end

  setfenv(f,env)
  return f,env
end

-- ***********************************************************************

function nmodule(modname)
  if nmodules.cache[modname] then
    return nmodules.cache[modname]
  end
 
  for i = 1 , #nmodules.lpath do
    local fname     = string.gsub(nmodules.lpath[i],"%?",modname)
    local f,env,err = loadtoenv(fname)
    if f ~= nil then
      nmodules.cache[modname] = env
      env._NAME = modname
      f()
      return env
    end
  end
  return nil,"module doesn't exist"
end

-- ***********************************************************************

A module then becomes just a Lua file with no other decorations.  Say, a
small utility class:

-- ****[util.lua]*************

function split(s,delim)
  local results = {}
  local delim   = delim or "%:"
  local pattern = "([^" .. delim .. "]+)" .. delim .. "?"
 
  for segment in string.gmatch(s,pattern) do
    table.insert(results,segment)
  end
 
  return results
end

function access(name,mode)
  local file = io.open(filename,mode)

  if file then
    file:close()
    return true
  else
    return false
  end
end

-- ****[end of line]**************

You can then include it with:

silly = nmodule('util')

path = silly.split(os.getenv("PATH"))
if not silly.access('/etc/passwd',"r") then
  print("not on a unix system")
end

  It wasn't hard to convert the one "module"ized project I have to use this
and it removed a bunch of lines of code (module(), local defs, etc).  Any
"globals" in the individual Lua files included via nmodule() become table
members, and it's up to the caller to determine the name under which the
file is located.  

  I don't see why a new method like this can't be accepted, along with the
older method.  

  -spc

Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
Mathias:
> I don't think you approach is verbose. Personally, I use the "simply
> return a local table from a 'module'" by myself and have not felt the
> need to do something more sophisticated yet. I even do without your
> "read-only" safety measure, thus my solution is even more basic.
Thanks! So I'm not off-track!


Sean Conner wrote:
>   The problem (as I see it) comes down to poluting the global namespace.
> module() basically loads some code and returns it in a new global table
> (plus maybe some magic).  I know that when I first started playing around
> with Lua modules it wasn't all that intuitive to me.
I Agree, but to me that is only one part of the story. Maybe my vision
is too constrained by my experience with statically typed languages
(mainly Java; some C++), but encapsulation and a clean, minimal
interface with client code is another point to consider.

>
>   Just in the past few days I came up with the following bit of code:
> [snip]
Ouch! Thanks. I only skimmed through it. It looks interesting, but
that's an issue somewhat orthogonal (even if strongly related).

I started this thread just because most of the solutions to the "module"
problem in the WIKI were (like yours) of this sort: reimplementing
"require", "module" or both, and that was the problem for me. I _was
able_, with moderate effort, to understand the code in itself, but what
worried me was that I didn't really understand all the implications,
lacking enough experience  with Lua. That was why _I_ felt really
uncomfortable with those approaches (please remember my Lua newbie POV).
(I really hate using a feature without understanding its limits).

>
>   It wasn't hard to convert the one "module"ized project I have to use this
> and it removed a bunch of lines of code (module(), local defs, etc).  Any
> "globals" in the individual Lua files included via nmodule() become table
> members, and it's up to the caller to determine the name under which the
> file is located.  
>
>   I don't see why a new method like this can't be accepted, along with the
> older method.  

Well, really I'm not knowledgeable enough to express an informed opinion
on that, nor on whether your technique is better than the other ones
proposed in the WIKI.
Please, don't get me wrong: I'm _NOT_ proposing that my approach (or a
similar one) be the standard. As I briefly mentioned on the originating
thread, I would welcome a widely accepted (maybe endorsed by the Lua
team) *cleaner* way to "declare" a module (throwing away, as is planned,
current "module", etc.).

But, until then, for me the main issue is to understand most of the
implications of my approach, i.e. writing a module with basic Lua
syntax, with clean, linear structure and no special support from custom
external functions (no "safe_require", "safe_module" or similar).
And whether that kind of module could be robust, efficient, well
encapsulated, generally applicable, with no pitfalls (or with well-known
ones!), i.e "simple and foolproof", even if a bit verbose (compared with
other approaches like yours, which rely on an additional framework).

Best Regards,

--- Lorenzo



Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Roberto Ierusalimschy
> But, until then, for me the main issue is to understand most of the
> implications of my approach, i.e. writing a module with basic Lua
> syntax, with clean, linear structure and no special support from
> custom external functions (no "safe_require", "safe_module" or
> similar).
> And whether that kind of module could be robust, efficient, well
> encapsulated, generally applicable, with no pitfalls (or with
> well-known ones!), i.e "simple and foolproof", even if a bit verbose
> (compared with other approaches like yours, which rely on an
> additional framework).

I would say that now the "endorsed by the Lua team" way to write
modules is like this: using clean and basic Lua syntax.

-- Roberto
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Petite Abeille-2-2

On Aug 18, 2010, at 2:24 PM, Roberto Ierusalimschy wrote:

> I would say that now the "endorsed by the Lua team" way to write
> modules is like this: using clean and basic Lua syntax

Then there is no "endorsed" way, as "clean and basic Lua syntax" is in the eye of the beholder. At least module() provide something a bit more concrete and functional than such a vagueness.

Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
In reply to this post by Roberto Ierusalimschy
Roberto Ierusalimschy wrote:

>> But, until then, for me the main issue is to understand most of the
>> implications of my approach, i.e. writing a module with basic Lua
>> syntax, with clean, linear structure and no special support from
>> custom external functions (no "safe_require", "safe_module" or
>> similar).
>> And whether that kind of module could be robust, efficient, well
>> encapsulated, generally applicable, with no pitfalls (or with
>> well-known ones!), i.e "simple and foolproof", even if a bit verbose
>> (compared with other approaches like yours, which rely on an
>> additional framework).
>
> I would say that now the "endorsed by the Lua team" way to write
> modules is like this: using clean and basic Lua syntax.
>
> -- Roberto
>
>
Thanks Roberto!
I'm glad to hear that my approach of writing modules is not simply a
"poor newbie's" way to avoid too much conceptual load! :-)

Well if that will be the "endorsed standard", it becomes still more
important for me to get feedback on my specific way of doing that
(potential problems, limits, etc.).

On a related note, may I assume from what you said that now the standard
contract for a module can be (incompletely) summarized as in the
following lines?

1. when loaded and called, a module's chunk should return a table
containing its "exported" symbols
2. a module should not create any global
3. ? any more items in the contract?

(BTW should this contract be the same for both Lua and C modules?)


Maybe laying down a well defined contract for a module could be useful
to find a common ground (I see that this thing of 5.2 dumping "module"
has stirred the water a little bit :-) )

I would add another point, which maybe is silly (sorry if it is "newbie
noise") but: what is *really* a module?

Please don't beat me up! But I read many times on this list and the WIKI
about different ways of loading a module, e.g. with "require" or
directly using "loadfile" (or whatever).
So is a module simply a Lua file? I didn't find a clear answer.
Maybe because the term "module" is often overloaded?

If there is no clear definition of what a module is (i.e., what is its
expected contract), I think it is difficult to talk about it with precision.

Take Java, for example, when you talk about a class it doesn't matter
what different CS books say about the OO concept of a class. A
_Java_class_ simply is what is defined in the Language specs. And it is
a fairly different beast than a C++ class. So when talking about Java, a
Java programmer has no doubt about what is meant with the term "class"
in that context.

Well, when it comes to Lua, sometimes I get really puzzled by what is
meant by the term "module". For a while I believed that a module was
what is defined by the "module" function. Then I began reading more of
the WIKI and this list, and I discovered that there are many different
ways of _defining_ a module (the contract I mean, not its
implementation, of course)!

I don't know really if this is good or bad (or maybe it's me that didn't
understand the topic well), but I would feel a bit safer knowing there
is a well defined entity behind the name "module".

Thank you all very much and sorry for the long post.

-- Lorenzo





Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Matthew Wild
On 18 August 2010 19:51, Lorenzo Donati <[hidden email]> wrote:

> Roberto Ierusalimschy wrote:
>>>
>>> But, until then, for me the main issue is to understand most of the
>>> implications of my approach, i.e. writing a module with basic Lua
>>> syntax, with clean, linear structure and no special support from
>>> custom external functions (no "safe_require", "safe_module" or
>>> similar).
>>> And whether that kind of module could be robust, efficient, well
>>> encapsulated, generally applicable, with no pitfalls (or with
>>> well-known ones!), i.e "simple and foolproof", even if a bit verbose
>>> (compared with other approaches like yours, which rely on an
>>> additional framework).
>>
>> I would say that now the "endorsed by the Lua team" way to write
>> modules is like this: using clean and basic Lua syntax.
>>
>> -- Roberto
>>
>>
> Thanks Roberto!
> I'm glad to hear that my approach of writing modules is not simply a "poor
> newbie's" way to avoid too much conceptual load! :-)
>
> Well if that will be the "endorsed standard", it becomes still more
> important for me to get feedback on my specific way of doing that (potential
> problems, limits, etc.).
>
> On a related note, may I assume from what you said that now the standard
> contract for a module can be (incompletely) summarized as in the following
> lines?
>
> 1. when loaded and called, a module's chunk should return a table containing
> its "exported" symbols
> 2. a module should not create any global
> 3. ? any more items in the contract?
>
> (BTW should this contract be the same for both Lua and C modules?)
>

Without wanting to speak for Roberto, I don't think you can ask
questions like these. Lua always aims to let you as the developer
decide on any "contracts" you want to impose. Decide what fits best
for your application, and use that. Still as you'll know if you've
been following the list, there are simple "best practices" (not
necessarily specific to Lua), one of which is to avoid globals if you
can help it - but that doesn't mean you can't or shouldn't if your
desired design is best implemented this way.

The module() (and luaL_register) function in 5.1 is bad precisely
because it doesn't allow for this flexibility - i.e. it creates
globals whether you want it to or not.

So now it is quite simple... what the module returns will be the
return value of require, what you return is up to you, whether you
create globals is up to you, whether you assign to _ENV or simply
create a new table is up to you, whether you add anything else to the
"contract" is also up to you. Lua does not dictate things like this.

Regards,
Matthew
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Roberto Ierusalimschy
> Without wanting to speak for Roberto, I don't think you can ask
> questions like these. Lua always aims to let you as the developer
> decide on any "contracts" you want to impose. Decide what fits best
> for your application, and use that. Still as you'll know if you've
> been following the list, there are simple "best practices" (not
> necessarily specific to Lua), one of which is to avoid globals if you
> can help it - but that doesn't mean you can't or shouldn't if your
> desired design is best implemented this way.

Note that a "standard contract" does not mean "the only
contract". Clearly we want to keep the flexibility that modules can do
whatever they want.  A "standard" contract sounds to me quite similar to
"best practices": what a module should do unless it has a clear motive
to do otherwise.


> So now it is quite simple... what the module returns will be the
> return value of require, what you return is up to you, whether you
> create globals is up to you, whether you assign to _ENV or simply
> create a new table is up to you, whether you add anything else to the
> "contract" is also up to you. Lua does not dictate things like this.

Lua does not dictate things like this, but in the specific case of
modules it "recomends" its external behavior. From PiL2, chapter 15:

  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.

  Starting in version 5.1, Lua defines a set of policies for modules
  and packages (a package being a collection of modules).

It goes on to define these policies:

  From the user point of view, a module is a library that can be loaded
  through require and that defines one single global name containing
  a table.  Everything that the module exports, such as functions and
  constants, it defines inside this table, which works as a namespace.
  A well-behaved module also arranges for require to return this table.

So, this was the old "standard" contract. The new one removes the part
about "defines one single global name containing a table."

But you are right that Lua does dictate anything about how to implement
this "recommended" behavior (calling 'module', using _ENV, etc.). That
is, there is a "standard contract", but not a standard way to implement
this standard contract. (And modules are free not to follow the
standard contract.)

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Roberto Ierusalimschy
In reply to this post by Lorenzo Donati-2
> On a related note, may I assume from what you said that now the
> standard contract for a module can be (incompletely) summarized as
> in the following lines?
>
> 1. when loaded and called, a module's chunk should return a table
> containing its "exported" symbols
> 2. a module should not create any global
> 3. ? any more items in the contract?

Roughly it is only rule 1. (We should not say what it should not do: a
module should not create any global; it also should not erase your hard
disk; it should not send emails to your friends; etc.)

But remember that this is a standard contract; modules are
free to use different contracts if needed (see related message).


> (BTW should this contract be the same for both Lua and C modules?)

Yes.

-- Roberto
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
In reply to this post by Matthew Wild
Matthew:

>> On a related note, may I assume from what you said that now the standard
>> contract for a module can be (incompletely) summarized as in the following
>> lines?
>>
>> 1. when loaded and called, a module's chunk should return a table containing
>> its "exported" symbols
>> 2. a module should not create any global
>> 3. ? any more items in the contract?
>>
>> (BTW should this contract be the same for both Lua and C modules?)
>>
>
> Without wanting to speak for Roberto, I don't think you can ask
> questions like these.
I'm sorry if I gave the false impression of wanting to pressure people.
If I expressed myself in such a way to give such an impression, please
let me apologize myself. English is not my mother tongue and I hope I
didn't convey my enthusiasm in learning Lua and my doubts in a way that
could upset people.

>Lua always aims to let you as the developer
> decide on any "contracts" you want to impose. Decide what fits best
> for your application, and use that. Still as you'll know if you've
> been following the list, there are simple "best practices" (not
> necessarily specific to Lua), one of which is to avoid globals if you
> can help it - but that doesn't mean you can't or shouldn't if your
> desired design is best implemented this way.
>
> The module() (and luaL_register) function in 5.1 is bad precisely
> because it doesn't allow for this flexibility - i.e. it creates
> globals whether you want it to or not.
>
> So now it is quite simple... what the module returns will be the
> return value of require, what you return is up to you, whether you
> create globals is up to you, whether you assign to _ENV or simply
> create a new table is up to you, whether you add anything else to the
> "contract" is also up to you. Lua does not dictate things like this.


Yes, I'm aware of the great degree of freedom Lua allows a developer.
That probably is my main source of confusion sometimes. As I mentioned
before, my background in Java and C++ (and very little experience in
highly dynamic languages) is probably hampering me in getting
the right mindset yet (the "big picture", I mean). I see I still need
much learning the "spirit" of Lua.
Thanks.
-- Lorenzo
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
In reply to this post by Roberto Ierusalimschy
Roberto Ierusalimschy wrote:

>
> Lua does not dictate things like this, but in the specific case of
> modules it "recomends" its external behavior. From PiL2, chapter 15:
>
>   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.
>
>   Starting in version 5.1, Lua defines a set of policies for modules
>   and packages (a package being a collection of modules).
>
> It goes on to define these policies:
>
>   From the user point of view, a module is a library that can be loaded
>   through require and that defines one single global name containing
>   a table.  Everything that the module exports, such as functions and
>   constants, it defines inside this table, which works as a namespace.
>   A well-behaved module also arranges for require to return this table.
>
Wonderful! I missed that! Thanks a lot!
> So, this was the old "standard" contract. The new one removes the part
> about "defines one single global name containing a table."
>
Ok. Got it.
> But you are right that Lua does dictate anything about how to implement
> this "recommended" behavior (calling 'module', using _ENV, etc.). That
> is, there is a "standard contract", but not a standard way to implement
> this standard contract. (And modules are free not to follow the
> standard contract.)
>
> -- Roberto
Ok. This clarifies very much! Thanks.
-- Lorenzo
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
In reply to this post by Roberto Ierusalimschy
Roberto Ierusalimschy wrote:

>> On a related note, may I assume from what you said that now the
>> standard contract for a module can be (incompletely) summarized as
>> in the following lines?
>>
>> 1. when loaded and called, a module's chunk should return a table
>> containing its "exported" symbols
>> 2. a module should not create any global
>> 3. ? any more items in the contract?
>
> Roughly it is only rule 1. (We should not say what it should not do: a
> module should not create any global; it also should not erase your hard
> disk; it should not send emails to your friends; etc.)
Fair enough! My bad :-)
>
> But remember that this is a standard contract; modules are
> free to use different contracts if needed (see related message).
>
>
>> (BTW should this contract be the same for both Lua and C modules?)
>
> Yes.
Ok. Good to know.
>
> -- Roberto
>
>
Thank you very much again!
-- Lorenzo
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Matthew Wild
In reply to this post by Lorenzo Donati-2
On 18 August 2010 21:29, Lorenzo Donati <[hidden email]> wrote:

> Matthew:
>>>
>>> On a related note, may I assume from what you said that now the standard
>>> contract for a module can be (incompletely) summarized as in the
>>> following
>>> lines?
>>>
>>> 1. when loaded and called, a module's chunk should return a table
>>> containing
>>> its "exported" symbols
>>> 2. a module should not create any global
>>> 3. ? any more items in the contract?
>>>
>>> (BTW should this contract be the same for both Lua and C modules?)
>>>
>>
>> Without wanting to speak for Roberto, I don't think you can ask
>> questions like these.
>
> I'm sorry if I gave the false impression of wanting to pressure people. If I
> expressed myself in such a way to give such an impression, please let me
> apologize myself. English is not my mother tongue and I hope I didn't convey
> my enthusiasm in learning Lua and my doubts in a way that could upset
> people.
>

No no, I was arguing against your question, not against the words you
used to ask it :)

Perhaps "I don't think you can ask questions like these." would have
been better as "I don't think Roberto (or anyone) can answer questions
like these for you."

Regards,
Matthew
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
Matthew Wild wrote:

> No no, I was arguing against your question, not against the words you
> used to ask it :)
>
> Perhaps "I don't think you can ask questions like these." would have
> been better as "I don't think Roberto (or anyone) can answer questions
> like these for you."
>
> Regards,
> Matthew
>
>
Ah! Thank you! :-) I'm glad I didn't by mistake offend anyone! I highly
value the time and the efforts of people on this list, so I would feel
really bad to be perceived as a "noisemaker" or something like that!

Well, this is really funny: it reminds me of an article on the history
of the Internet I read some years ago. IIRC it explained the genesis of
the emoticons ("smileys") as a way to overcome the "human relationship"
limitations of a pure text communication medium among people scattered
over a huge area, possibly having different backgrounds and coming from
different communities.
Well maybe I should learn how to use them better ;-) :-)
Best Regards,
-- Lorenzo
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Javier Guerra Giraldez
On Wed, Aug 18, 2010 at 3:58 PM, Lorenzo Donati
<[hidden email]> wrote:
> Well, this is really funny: it reminds me of an article on the history of
> the Internet I read some years ago. IIRC it explained the genesis of the
> emoticons ("smileys") as a way to overcome the "human relationship"
> limitations of a pure text communication medium among people scattered over
> a huge area, possibly having different backgrounds and coming from different
> communities.
> Well maybe I should learn how to use them better ;-) :-)

http://lua-users.org/lists/lua-l/2006-09/msg00767.html



--
Javier
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Lorenzo Donati-2
Javier Guerra Giraldez wrote:

> On Wed, Aug 18, 2010 at 3:58 PM, Lorenzo Donati
> <[hidden email]> wrote:
>> Well, this is really funny: it reminds me of an article on the history of
>> the Internet I read some years ago. IIRC it explained the genesis of the
>> emoticons ("smileys") as a way to overcome the "human relationship"
>> limitations of a pure text communication medium among people scattered over
>> a huge area, possibly having different backgrounds and coming from different
>> communities.
>> Well maybe I should learn how to use them better ;-) :-)
>
> http://lua-users.org/lists/lua-l/2006-09/msg00767.html
>
>
>
Great link! :-)
Now my Lua problems have been superseded by the problem of stop
laughing! :-))
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Daurnimator
In reply to this post by Lorenzo Donati-2
On 19 August 2010 04:51, Lorenzo Donati <[hidden email]> wrote:
> On a related note, may I assume from what you said that now the standard
> contract for a module can be (incompletely) summarized as in the following
> lines?
>
> 1. when loaded and called, a module's chunk should return a table containing
> its "exported" symbols
> 2. a module should not create any global
> 3. ? any more items in the contract?

These would be reasonable starting points for "best practices".

I would rephrase 2. to: "a module should be fully self contained, not
creating or using globals other than the base libraries"

Others conditions might be:
Don't use a debug hook for longer than a function's duration; and
bubble any other hooks up;
Don't change common metatables (eg, string/lightuserdata)

> (BTW should this contract be the same for both Lua and C modules?)

Yes; using luaL_register with a NULL argument leaves the table on the
stack, so you can "return 1".

Daurn.
Reply | Threaded
Open this post in threaded view
|

Re: Basic, no fuss, no magic, foolproof module pattern. [Was: require, module, globals and "magic"]

Luiz Henrique de Figueiredo
> I would rephrase 2. to: "a module should be fully self contained, not
> creating or using globals other than the base libraries"

Surely a module can use other modules it requires. If all required modules
behave well, then the module in question can do
        local random=require"random"
and all is well. But if it require modules that only set a global variable,
then the module in question can only do
        require"random"
        local random=random
or use the global "random".