[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: module & 5.2
- From: Petite Abeille <petite.abeille@...>
- Date: Sun, 1 Apr 2012 14:47:29 +0200
In 5.1, one could do the following out-of-the-box, courtesy of module:
(1) define a self-contained, self-registered module with a one-liner
(2) define multiple modules per source file
(3) package multiple lua source files into one file, courtesy of cat, without further ado
(4) package multiple lua source files into one compiled file, courtesy of luac -o, without further ado
Not so much with 5.2 as:
(a) module is deprecated
(b) even though module is still defined and enabled by default, its implementation is not backward compatible in terms of (2), (3) and (4) which renders it rather pointless and dangerous
So what to do to get the same level of functionality in 5.2?
To allow for feature parity with 5.1, it looks like in 5.2 a module might need to be defined as follow:
do -- (I) module block
local package = require( 'package' )
local _ENV = {} -- (II) self-contained environment
-- module implementation
package.loaded[ 'module' ] = _ENV -- (III) self-registration
end
(I) The block provides support for multiple module per file (2), and concatenation of source files (3)
(II) _ENV provides a self-contained environment
(III) package.loaded provides self-registration
So instead of a one-liner as in 5.1, in 5.2 one now needs all of the above boilerplate (block, _ENV, package.loaded) to get functional parity.
But life goes on, so here is a small reimplementation of module for 5.2:
--8<--
do
local select = select
local package = require( 'package' )
local _ENV = {}
local function module( aName, ... )
local aModule = package.loaded[ aName ]
if aModule == nil 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
package.loaded.module = module
end
-->8--
And some usage examples:
$ cat TestA.lua
do
local print = print
local module = require( 'module' )
local _ENV = module( 'TestA' )
print( 'TestA', _NAME, _ENV )
end
$ cat TestB.lua
do
local print = print
local module = require( 'module' )
local _ENV = module( 'TestB' )
print( 'TestB', _NAME, _ENV )
end
$ cat TestC.lua
do
local print = print
local module = require( 'module' )
local TestA = require( 'TestA' )
local TestB = require( 'TestB' )
local _ENV = module( 'TestC' )
print( TestA, TestB )
print( 'TestC', _ENV )
end
Run from individual source:
$ lua TestC.lua
TestA TestA table: 0x100106150
TestB TestB table: 0x100106b00
table: 0x100106150 table: 0x100106b00
TestC table: 0x100107020
Packaged as one lua file:
$ cat module.lua TestA.lua TestB.lua TestC.lua > TestAll.lua
$ lua TestAll.lua
TestA TestA table: 0x100104f70
TestB TestB table: 0x100100c50
table: 0x100104f70 table: 0x100100c50
TestC table: 0x100100d90
Packaged as one luac file:
$ luac -o TestC.luac module.lua TestA.lua TestB.lua TestC.lua
$ lua TestC.luacTestA
TestA table: 0x100105b80
TestB TestB table: 0x100100b80
table: 0x100105b80 table: 0x100100b80
TestC table: 0x100105ca0
While the above "works" in terms of (1), (2), (3) and (4), it doesn't strike me as a change for the better as now everyone and their dog will need to re-invent some, part, or variation of the module features, with all the additional chrome, boilerplate and incompatibilities that ensue. Looks like a big step backward altogether.
Anyway, how do people implement their modules in 5.2? With the same level of functionality as in 5.1?
Feedbacks and suggestions welcome.