lua-users home
lua-l archive

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


On Feb 18, 2013, at 3:43 PM, Gavin Kistner <phrogz@me.com> wrote:

> This works fine for this project where I only have two files. How would others suggest enforcing the same pattern for a different project that has many files all augmenting the same table?

Perhaps you are over thinking it? :)

Keep in mind the fundamentals: a module is just a table. Nothing more, nothing less.

As soon as one finds a reference to a module table, one is free to manipulate it any way one sees fit. 

This can be as simple as:

do
  local _ENV = require( 'mymodule' ) -- assuming 'mymodule' is defined somehow

  function bar() end -- add a new function to mymodule
end

Of course, one could do the reverse and define multiple modules in one file, for example:

do
  local _ENV = {}

  function foo() end

  package.loaded[ 'foo' ] = _ENV
end

do
  local _ENV = {}

  function bar() end

  package.loaded[ 'bar' ] = _ENV
end

do
  local _ENV = {}

  function baz() end

  package.loaded[ 'baz' ] = _ENV
end

Avoiding a 'return' in the module definition is rather handy as it allows one to combine multiple modules in one physical file, be it Lua code or bytecode, while coding or while deploying, or any combination thereof.

As an added bonus, defining modules in terms of _ENV enforces locality. 

As this is/was a rather common pattern in 5.1, courtesy of the now deprecated 'module' function, one can of course reimplement it in 5.2 as well: 

local function module( aName, ... )
  local aModule = package.loaded[ assert( aName ) ]

  if type( aModule ) ~= 'table' then
    aModule = {}
    aModule._M = aModule
    aModule._NAME = aName
    aModule._PACKAGE = aName:sub( 1, aName:len() - ( aName:reverse():find( '.', 1, true ) or 0 ) )

    package.loaded[ aName ] = aModule

    for anIndex = 1, select( '#', ... ) do
      select( anIndex, ... )( aModule )
    end
  end

  return aModule
end

Then one can define modules in 5.2 with all the convenience and features of 5.1, and then some:

local _ENV = module( 'dwim' )

…

FWIW, here is an example of the above principles at work:

http://alt.textdrive.com/svn/altdev/Mail/DB.lua

But sadly, now, in 5.2, every Tom, Dick, and Harry has to reimplement and reinvent their own half-baked way to handle module definitions. A sad step back from 5.1 where 'module' naturally, meaningfully, and predictably, complemented 'require'. Oh well, every one is entitled to their own mistakes. Even Lua's authors.