Mis-Understanding External Modules

I’m starting to really confuse myself (happens when the coffee wears off).

I’ve been studying up on how to utilize external modules appropriately. Or at least not use them incorrectly.
But I’m still having issues.

Here are the links I’ve been reading and practicing from:

http://www.coronalabs.com/blog/2011/08/12/tutorial-simple-modular-coding-technique/
This post is very cool, and gives some great points on how to stop duplicating code, by putting your mostly used functions inside one place - then calling that single file across multiple modules.
What confuses me is level1.lua does not have the module(…, package.seeall) in the top, as I would expect. Is it not needed?

Now, when you go to this post:
http://www.coronalabs.com/blog/2011/07/06/using-external-modules-in-corona/
I think I see the opposite in effect. The example of their level1.lua has the module(…, package.seeall) in the top.

Like many apps, I plan to put all my screen content inside separate screen.lua files. I also plan to place common functions inside a single Functions.lua file. (btw, is it best to reference the Functions.lua from inside the main.lua or from inside each screen.lua file?
I intend for my main.lua to be simply the calling-entity to everything else.

I come from a PHP web background, and I usually place every custom function inside a single file, and call that file from each page. (even if most of the functions are not used in that page) Perhaps this is bad practice for the mobile side?

And inside each screen.lua I am calling the removeSelf() function, to clean up memory.
Does this clean up the references to external modules too? I can’t image it does, since the removeSelf() is attached to an display object.

Example:

-- level1.lua (pulled this from the first link above)  
--------------------------------------------------  
function new()  
 local gamefunctions = require( "gamefunctions" ) --\> this is called inside the level1.lua, not main.lua?  
 -------more game code below.........  
  
end  

And back to the original concern, when do I really need to place module(…, package.seeall) in the top of a file, and when don’t I?
It seems I can leave it out, and I get the same results (at least from what I’ve tested)

thanks guys!

[import]uid: 154122 topic_id: 28273 reply_id: 328273[/import]

Hi Marc,

Lots of questions here. :slight_smile: I’ll try to answer a few of them.

module(…, package.seeall) is now depreciated in Lua and you should avoid using it. Look for a code example that uses something like the following.

local M = {}  
  
local function myFunction()  
 --function code here  
end  
M.myFunction = myFunction  
  
return M  

From a memory management standpoint, you should probably just keep your “common” functions in main.lua. If you will use them frequently, there is little reason to load and unload them per new scene. You can also put them in an external module like above and call them that way.

There are many, many examples around the forums on ways to structure your app. Some prefer the object-oriented approach, others don’t. Some devs prefer to modulize almost everything, others just keep most of it “local” in main.lua. There isn’t really a “right or wrong” method, as long as you are absolutely aware of memory and cleanup techniques based on your chosen approach. Memory leaks are obviously bad for all concerned!

Brent

[import]uid: 9747 topic_id: 28273 reply_id: 114236[/import]

@brent:

really there is no difference between:

local M = {}  
   
local function myFunction()  
 --function code here  
end  
M.myFunction = myFunction  
   
return M  

and

local M = {}  
  
function M:myFunction()  
 --function code here  
end   
return M  

I personally prefer the latter, as there is no performance difference between the two, or memory difference. So the first example is just writing an extra line of code.

Again though it’s personal preference as either way is acceptable [import]uid: 84637 topic_id: 28273 reply_id: 114292[/import]

@Danny

The bottom one is prettier, but I prefer the top one so that I can bunch all the exposed functions on the bottom of the file so I can remember the public functions in the future :slight_smile: [import]uid: 144908 topic_id: 28273 reply_id: 114295[/import]

@Danny
The second one contains the parameter [self] as the first parameter for the function. But replacing the : with a . would make them effectively identical.

The way “require” works is as follows:
1)It parses the file, as if calling the entire contents of the file as a function. You can even use (…) to get the filename as if it was a function parameter.
2)It places anything returned from parsing your file into packages.loaded[YourFileName], and makes sure that any further require calls to the same filename will not actually parse your file again, but instead just return a reference to packages.loaded[YourFileName]

What this means is that the only real way to clean out the memory used by a file would be to clear out the reference to the returned data in packages.loaded. It also means that multiple require calls are cheap, since it only actually parses your file once, and afterwards will just return a stored object. It also means you can put do-once initialization code outside of any functions in your file, since it will only be called once, during parsing.

the module command is often suggested to be avoided, because it has issues with creating extra, potentially unintended data as globally accessible objects. A good explanation of why to avoid module is here: http://lua-users.org/wiki/LuaModuleFunctionCritiqued (it’s a big file, but it gets to some primary complaints quickly). As well, since it puts new variables in the global table, it is more difficult to clean up a previous require (since package.loaded is no longer the only reference to the required object). If you really need to make something globally accessible, without having to use require in each file you can do this:

local M = {}  
   
local function myFunction()  
 --function code here  
end  
M.myFunction = myFunction  
   
\_G.M = M --This puts it in the global table  
  
return M --This puts it in packages.loaded  

_G is a shortcut to globally accessible variables, but if you do this, you need to make sure to do _G.M = nil if you want to clear the loaded file from memory.

In any other file that doesn’t declare “local M”, you can use M without having to require it. [import]uid: 134101 topic_id: 28273 reply_id: 114337[/import]

@Ntero, exactly [import]uid: 84637 topic_id: 28273 reply_id: 114343[/import]