Modules Tutorial |
|
Modules can be easily created by creating a file a.lua with the following content:
module(..., package.seeall); function foo() print("Hello World!") end
The special table package will be explained later.
To now use this new module just do:
> require "a" > a.foo() Hello World!
To reload the module is a bit more tricky, because Lua caches already loaded modules. Still its possible by deleting the entry from the special package.loaded table.
Say we changed foo in a.lua to now print "Hello Module!" instead.
If we just continued in the same session as above the following would happen:
> require "a" > a.foo() Hello World!
This was not what we wanted.
So we reload the module.
> package.loaded.a = nil; require "a" > a.foo() Hello Module!
Another nice thing is that modules can be named arbitrarily. Say we think that "a" for a module name is a bit short or that reallylongmodulenamesomedamnprogrammerchose is a bit long. We can then do the following:
> require "a" > bar = a > bar.foo() Hello Module!
This works as a module is just a call table of functions.
Also the call to module via ... allows us to just rename the file to rename the module.
Now consider the following module secret.lua:
module(..., package.seeall); secret = 42 function reveal_some() return (secret % 2) end function foo() print("Hello World!", reveal_some()) end
As we will see it is not as secret as we wished:
> package.loaded.secret=nil require "secret" > secret.foo() Hello World! 0 > secret.reveal_some() > = secret.reveal_some() 0 > = secret.secret 42 > secret.secret=1 > = secret.reveal_some() 1 > secret.foo() Hello World! 1
Not only can we access the secret value, we can even change it and directly access the reveal_some function. That was not what we wanted!
However using the special "local" keyword, we can limit the scope to the current module only.
module(..., package.seeall); local secret=42 local function reveal_some() return (secret % 2) end function foo() print("Hello World!", reveal_some()) end
And now it really does, what we wanted. secret and reveal_some are now only accessible from within the module.
As already mentioned above Lua uses the special table package to manage modules.
This table has some interesting fields.
> table.foreach(package, print) preload table: 0x806d058 loadlib function: 0x806cbe0 loaded table: 0x806b930 loaders table: 0x806cc50 cpath ./?.so;/usr/local/lib/lua/5.1/?.so;/usr/lib/lua/5.1/?.so;/usr/local/lib/l .. ua/5.1/loadall.soconfig / ; ? ! - path ./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lu .. a;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua;/usr/share/lua/5 .. .1/?.lua;/usr/share/lua/5.1/?/init.lua
Interesting is the package.path, where Lua searches for the files and replaces '?' with the filename. Of course on your (Windows) system this might be different.
package.loaded is a table, where the already loaded modules are stored by name and can be modified as seen above.
Last but not least package.seeall is the special function, which can be given to module to allow inheritance of the global environment.
Note that this has funny side effects as someone can then call for example a.math.sin(x).