Hi guys!
I just created a neat little object system for Lua (5.1) that does
pretty much exactly what I want.
You use it like this:
newThing = object(function() -- could add arguments here too
var1 = 1
local var2 = 'test'
function method1()
var1 = var1+1
end
local function method2()
return string.sub(var2, 2) -- can use globals as normal
end
end)
thing = newThing()
thing.var1 = 5
thing.method1() -- yeah, just dot, no colon
The point is: You just put all fields and methods inside one big
definition function. What you declare 'local' will be private;
everything else will become part of the object.
The great advantage: No need to ever write 'self.'. (I'm coming from
the Java world and I just hate having to insert 'self' all the time
(or at all).)
Also, all non-local variables are both readable and writeable from
outside.
Usually I write a module 'plain' first (everything top-level) and
decide to make it an object later. With this system, I can do that
without changing one bit in the code.
There is one little caveat: The definition function must not be
recursive (making more objects of its own kind); that would probably
break the setfenv trickery. Making more objects within methods is fine.
Here's how it is implemented. Attention, it's short - 14 lines with
comments and whitespace :)
*****
-- make an object from a definition function.
-- all variables and functions declared in the definition function
without 'local'
-- are automatically part of the new object.
function makeObject(definition, ...)
-- make an environment that inherits all the globals
local env = setmetatable({}, {__index = function(_, k) return _G[k]
end})
setfenv(definition, env)(...)
return env
end
-- the beloved curry operator (for one fixed arg)
function curry(f, a) return function(...) return f(a, ...) end end
function object(definition) return curry(makeObject, definition) end
*****
You can also put it all in one function, but it still ends up taking 7
LoC:
***
function object(def)
return function(...)
local env = setmetatable({}, {__index = function(_, k) return
_G[k] end})
setfenv(def, env)(...)
return env
end
end
***
Is this old? Is this new? Has this been done before? I love this and I
think I'll be using it to death. :)
Cheers,
Stefan