## Policies for writing Lua modules

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Contact:

### Policies for writing Lua modules

Hi all,

I am hereby sharing with you all some short and nice articles for writing modules in Lua in a clean way.
Actually, the authors are not trying to define "the way to go" or stand as an authority, but they are just sharing their thoughts on the topic,
and their own policies they tend to stick to, mentionning eventually the pros (and cons).

I found the content very much valuable, as there are very much interesting things to learn from, and it might influence your actual style.
Plus, they are all written by some fairly experienced programmers, that's the very reason I am posting them here.

The article who originated is from Hisham Muhammad:
Link: How to write Lua modules in a post module world

The second article is a straight response to the first one. It is from Pierre Chapuis:
Link: How I write Lua modules

Prior to these article, there is also a great post from Kikito, which provides some nice policies/guidelines for module
privacy. The article raises some good points that are also mentionned in the previous articles. Also, it is based on
MiddleClass.

Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

### Re: Policies for writing Lua modules

I've taken to writing my code like this:

Code: Select all

local actor = {
_VERSION = 'actor.lua 0.1',
_COMPONENT = "actor",

init = function(self)
self._co = { dt = 0 }
end,
}

actor.__index = {

cowrap = function(self, func)
return self
end,

corun = function(self, ...)
if not self:codone() then
local err, msg = coroutine.resume(self._co.thread, ...)
if err == false then
end
end
end,

cowait = function(self, secs)
repeat
local dt = coroutine.yield(true)
if not secs then
self._co.dt = 0
return dt
end
self._co.dt = self._co.dt + dt
until self._co.dt >= secs
self._co.dt = self._co.dt - secs
return secs
end,

codone = function(self)
if not self._co.thread then return true end
end
}

return actor

This particular piece is part of an entity-component style I've adopted. I'm kind of living in a post-inheritance world where I like to do everything via copying, and I decided that the __index subtable is the perfect place to put the mixin functions.

But yeah, the return local module style has become the dominant form for Lua 5.2, and it's feeding back into 5.1 code, and even in the javascript world their way of declaring modules has been to just fill up and object with useful things.

richardperkins
Prole
Posts: 9
Joined: Tue Jan 07, 2014 6:20 am

### Re: Policies for writing Lua modules

These articles were extremely helpful, and I thank you for that.

I have adopted two styles from this based on whether I want the "module" to be instantiated or not.

Inny, your technique intrigues me. How exactly do you implement your modules and/or what is the purpose or perk(s) to modelling in that way?

bekey
Party member
Posts: 255
Joined: Tue Sep 03, 2013 6:27 pm

### []

-snip-
Last edited by bekey on Fri Jan 24, 2014 2:22 am, edited 1 time in total.
love2d.org forum removal spell: http://pastebin.com/iVqJrbKN

qaisjp
Party member
Posts: 490
Joined: Tue Sep 04, 2012 10:49 am
Location: United Kingdom
Contact:

### Re: Policies for writing Lua modules

Very interesting...
Lua is not an acronym.

Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Contact:

### Re: Policies for writing Lua modules

bekey wrote:Commenting as opposed to bookmarking.
Is this thread from the inner party? Or did I just not notice it first time around.
Nope, I posted it in the General section. Glad you find it useful

SiENcE
Party member
Posts: 785
Joined: Thu Jul 24, 2008 2:25 pm
Location: Berlin/Germany
Contact:

### Re: Policies for writing Lua modules

I have one general problem by writing modules/libs.

Do i include middleclass into the library...should i use my own class code (no good) or should i include a reference and the user has to get this library himself (possible version conflict).

Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Contact:

### Re: Policies for writing Lua modules

SiENcE wrote:I have one general problem by writing modules/libs.

Do i include middleclass into the library...should i use my own class code (no good) or should i include a reference and the user has to get this library himself (possible version conflict).
I think it all depends on you. Matter of taste.
Class implementations are useful, and I would personally use one in a large project, where several classes are created, where instantiation/inheritance is heavily used because it has to, to dispose of reusable code. Games, for instance.
When writing a module library (or a library consisting of several modules), I won't include a class library, because I do not feel like I should.
Rather, i will hardcode my classes, because it is very simple to do so. The lesser dependencies, the better.

Code: Select all

local ModuleClass = {}
ModuleClass.__index = ModuleClass
function ModuleClass:new(...)
local instance = {...}
-- some dirty work
return setmetatable(instance, ModuleClass)
end
And if I want inheritance:

Code: Select all

local ModuleClass = {}
function ModuleClass:new(...)
local instance = {...}
-- some dirty work
self.__index = self
return setmetatable(instance, self)
end
Or maybe, if I need a generic class constructor, to be reused, I'll have this function internally defined:

Code: Select all

local class = function(...)
local klass = {}
klass.__index = klass
klass.__call = function(_,...) return klass:new(...) end
function klass:new(...)
local instance = setmetatable({}, klass)
klass.__init(instance, ...)
return instance
end
return setmetatable(klass,{__call = klass.__call})
end

Also, your module doesn't have to be a class, explicitely. Sometimes, it can just be a set of utility functions, returned into a table. The end-user is not
supposed to instantiate from the module, but just use the functions. Example, SOR.

I will suggest taking a look at The Great vrld's libraries, The Great Kikito's librairies, The Great Bartbes' librairies for reference. Not that they are the best ones ever (oh-well, they are, indeed ) but they contain very clean code. Shameless plug, mine can also serve as reference.
Pay attention at how module are written, how internal classes are defined, it might help.

I will also mention Class-Commons, that you can use to define classes in your code, so that the end-user will use your code with his favourite OOP library (though it has to be Class-commons compatible). For instance, the Great Vrld used it in HardonCollider.

Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

### Re: Policies for writing Lua modules

richardperkins wrote:These articles were extremely helpful, and I thank you for that.

I have adopted two styles from this based on whether I want the "module" to be instantiated or not.

Inny, your technique intrigues me. How exactly do you implement your modules and/or what is the purpose or perk(s) to modelling in that way?
My style is, at core, this:

Code: Select all

local Module = {
init = function(self) end
}
Module.__index = {
}
return Module

This is a completely stripped down Lua object suitable for being used as a metatable like this: local instance = setmetatable({}, Module); Module.init(instance)

When I mentioned entity-component, I mean I learned a few things from crafty.js and instead of inheriting between classes, the instances themselves are copies of their Component classes.

Code: Select all

local player = {}
for k, v in pairs(Sprite.__index) do
if player[k] == nil then player[k] = v
end
Sprite.init(player);

Developed a little further, I can write code like so:

Code: Select all

local player = entity();
player:require(sprite)

That actually raises a good question, how do you guys like require as the verbiage for how an entity uses a component? some time addComponent is used, and in the javascript, extend is what you see commonly (like even in jquery they have $.extend). ejmr Party member Posts: 302 Joined: Fri Jun 01, 2012 7:45 am Location: South Carolina, U.S.A. Contact: ### Re: Policies for writing Lua modules Thank you Roland for sharing the articles—great reads. Inny wrote:That actually raises a good question, how do you guys like require as the verbiage for how an entity uses a component? some time addComponent is used, and in the javascript, extend is what you see commonly (like even in jquery they have$.extend).
This is bike-shedding, but personally I like ‘requires’ more than ‘require’ because I think of variables in code as if they were third-person pronouns in English grammar. Since ‘require’ already has a meaning in Lua maybe something like ‘uses’ or ‘includes’ would be better. Since you say, “…how an entity uses…,” that tips my preference towards ‘uses‘ as the method name.

But again, that is all just bike-shedding. Conceptually I like the idea a lot.
ejmr :: Programming and Game-Dev Blog, GitHub

### Who is online

Users browsing this forum: No registered users and 3 guests