Everything you need to know about lua modules

Hi folks,
I've done tons of research and testing on the proper way to write a module in Lua. So I thought I'd share it with you.

Most people would simply write a module like a regular script starting with
module(..., package.seeall)
Have a look here to get some ideas about why it is a bad practice.

What you should write, according to many gurus is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
-- File: myModule.lua
-- Author: me
 
-- ***************************
-- Private part of your module
-- ***************************
 
local myOtherModule = require( "myOtherModule" )
 
local privateVar1 = "Foo"
local privateVar2 = 23
 
local privateFunction1()
 -- do something
end
 
local privateFunction2()
 -- do something else
end
 
 
-- The module table
local myModule = {}
 
-- **************************
-- Public part of your module
-- **************************
 
myModule.publicVar1 = 5
 
myModule.publicFunction1 = function()
 myModule.publicVar1 = 22
 -- do something
end
 
myModule.publicFunction2 = function()
 -- do something else
end
 
return myModule

Thankyou :)
Is there any performance loss using package.seeall?
And am I correct in believing

require("modulename")

is shorthand for

modulename = require("modulename")

in that they both load the module in global scope, and using local as you have is much better?

I can't really tell about the performance but it should be very similar, if not completely equal.

As for your second question, require("modulename") is different from modulename = require("modulename"). The first code just loads the module but you can't access it. The second code loads the module and assign a reference to a global variable "modulename". Which is something you should avoid if you can. If you don't/won't, be sure to set the global variable to nil when you're done with it.

Thanks for the pointers Seth, I'm going to modify my code according to your advice! I have a little design challenge that I hope you can help me with:

I call some modules (level1.lua, level2.lua, etc) from my main.lua to change scenes. However, every module needs to perform a particular task (construct the same building, for example). So I would like to put the function that constructs the building into its own module (building.lua). However, I cannot successfully get the ‘level’ modules to call the functions in the ‘building’ module.

Can modules call functions within other modules? (I think your example above shows the calls from main). If modules can call functions within other modules, can you show a simple example? It would be much appreciated. Thanks!

Can modules call functions within other modules? Hell yeah!

1
2
3
4
5
6
7
8
9
10
11
12
13
main.lua:
local level1 = require("level1")
local level2 = require("level2")
 
level1.lua:
local building = require("building")
local eiffelTower = building.constructEiffelTower()
-- do stuff, like destroy the Eiffel tower
 
level2.lua:
local building = require("building")
local eiffelTower = building.constructEiffelTower()
-- do stuff, like paint the Eiffel tower

Thanks Seth! I was doing just that and it wasn't working for me. I'm going to re-write a simple 'main' and a couple level 'modules' again and build back up from there. My modules are large and I'm sure I must have a bug I'm not seeing.

I like your proxy dersign - it's straightforward! I was using the director class (director:changeScene("level1")).

I've been using :

1
2
3
4
require("object")
newobject = object:new()
print(newobject.retVar1()) -- "Foo"
print(newobject.retTotal()) -- "15"

Thanks for the detailed explanation! Would the change scene alternative described in this post be as efficient even though it uses module(..., package.seeall)? http://developer.anscamobile.com/forum/2011/02/14/easy-screen-transitions-director-alternative

I havent bothered to download the file and try it, so I may be talking out of place here, but from the description, I can't see how using package.seeall would be useful.
As far as I can see, it allows a module to see other modules, and if this one is taking a screenshot, and returning it, it doesn't use any other modules, so is just a (albeit negligible in the scheme of things) waste of resource.
(on iphone, so can't see the code anyways)
:)

I checked the texture memory in my simple game (animated sprites with physics, scrolling background). It looks like the code cleans it up nicely:

1) shortly after launching game from splash screen:
game curr texture memory used (bytes) = 4005888

2) when the game is in play:
curr texture memory used (bytes) = 2957440

3) initial bytes when first changed back to splash screen:
curr texture memory used (bytes) = 1114112 then

4) sitting at splash screen
curr texture memory used (bytes) = 65536

This is the code in the main.lua (pass sceneGroup back from other modules):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
--main.lua
-- from x-pressive.com
 
function ChangeScene(NextScene)
 
-- MAKE A SCREENSHOT OF THE SCENE TO REMOVE,
-- CENTER & SCALE SCREENSHOT TO CORRECT SIZE
local Screenshot  = display.captureScreen( false )
Screenshot.yScale = (display.contentHeight/ Screenshot.height)
Screenshot.xScale = Screenshot.yScale
Screenshot.x      = display.contentWidth*.5
Screenshot.y      = display.contentHeight*.5
        
-- REMOVE THE CURRENT SCENE (SCREENSHOT STAYS)
CurrScene:removeSelf()
                
-- CREATE A NEW SCENE
CurrScene = NextScene.CreateScene()
 
-- SCENE TRANSITION     
display:getCurrentStage():insert(Screenshot)
 
-- TRANSITION TO NEXT SCREEN    
transition.to(Screenshot, {
 
time = 400, 
xScale = .5, 
yScale = .5, 
rotation = 0, 
transition = easing.inQuad,
onComplete = function() 
Screenshot:removeSelf(); Screenshot = nil 
 
                                                        
end 
}) 
views:1903 update:2011/10/5 21:23:48
corona forums © 2003-2011