lua-users home
lua-l archive

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

On Mon, May 4, 2009 at 8:35 AM, Luiz Henrique de Figueiredo wrote:
> I don't see a problem here at all. Take for instance my mathx, which
> extends the standard math library with the functions available in C99.
> I think it's quite natural to ad those to math instead of creating a
> mathx table.

That way leads to problems when programming in the large.

Module A (written by Author A) needs to use both Module B (written by
Author B) and Module C (written by Author C).  Now, Module B happens
to use Author D's (i.e. lhf's) lmathx utility library, which injects
the function math.erf, while Module C happens to use Author E's
alternative high performance math library that also injects a function
math.erf but with a slightly different and incompatible definition
[1].  This is a conflict, and Author A needs to contact the other
authors to resolve it.  It is a failure in modularity [4].

One solution to this problem proposed in ExtensionProposal [2] was for
the core Lua team, which maintains the standard tables (math, os,
string, etc.), to define the interface, though not necessarily the
implementation, to extended functions like math.erf.  This way, the
math libraries implemented by Author D and E are less likely to
conflict, bar implementation bugs or ignoring the interface
specification.  Or if they do conflict, only the conformant one would
be allowed to inject into math.

A simpler, perhaps more practical, solution to the problem is for
authors simply to not inject into any other author's modules.  An
author may, however, inject -from- another module into theirs (via
copy or metatable fallback), and a client may make "math" a local
variable aliasing another module:

  local math = require 'my.special.math.functions'

  assert(math.erf) -- a new function
  assert(math.sqrt == _G.math.sqrt) -- injected -from- original

On Mon, May 4, 2009 at 10:55 AM, Philippe Lhoste wrote:
> I think that collision risk is the main issue, indeed, when you mix and
> match various libraries (particularly those with the proverbial kitchen
> sink! ;-)).
> Java people resolved it with the package names using domain names as base...

Long package names become not that cumbersome when using aliasing like
the above.

I've had criticisms of the Lua module system design, primarily the
optional module function [3].  In fact, simply by naming a module with
the prefix "math." and implementing it with the module function, you
may automatically inject into the math table:

  -- math/erf.lua
  function erfc(x) return 0 end -- a very, very rough approximation ;)

  -- c.lua
  local m = require "math.erf"

  -- b.lua
  require "mathx"
  print(math.erf(1)) -- opps! (conflict)

  -- a.lua
  require "c"
  require "b"

The above reasoning implies this rule:

-->  A module should not have the same name as any other module.
Furthermore, when the "module" function is used to define modules, a
module name should not conflict with any other variable in any other
module table.

This condition is stronger and more difficult to enforce than in
module systems of other languages, where typically we only need to
worry about the former condition.  Furthermore, the condition has
typically been unstated.

Lacking enforceability, this leads to the corollary

--> A module name should not have the same dotted name prefix as any
other module unless the authors of the two modules cooperate in taking
appropriate steps to avoid conflict.

Lacking any common convention, this leads to another corollary:

--> Don't use dots in module names (when modules are implemented using
the "module" function).

Perhaps that is draconian.  I prefer instead the rule

--> Don't use the "module" function.