Prototyping in Lua December, 2011
One of the hardest things to get my head around in JavaScript (Besides "this") was prototyping. I wasn't sure if it was prototyping itself that was hard to grok (It seemed amazingly simple to me in principle) or if it was how JavaScript implemented it. I thought it would be an interesting exercise to explore how another prototypal language worked to see where the difficulty lay. So let's take a look at how Lua implements prototyping (Disclaimer: I only have a passing knowledge of Lua so please excuse my naïveté).
Lua "tables" form the basis of objects. They are essentially hash tables, à la JavaScript objects. Prototyping in Lua is enabled by two actions; first setting the objects' metatable (Which can be any table) and second, setting the prototype field in that metatable (Which is the __index field). Here is how it works (NB: see here about the use of colon vs. dot. Compare it to call/apply in JavaScript):
-- Create the prototype Greeting = { hello = 'hello' } function Greeting:say_hello() print(self.hello) end -- Create an object lolcat = { hello = 'hai' } -- Set the meta table (A table where metadata is held), in this case we'll just set it to be the object itself setmetatable(lolcat, lolcat) -- Set the prototype lolcat.__index = Greeting
Other than the setting of the metatable I'd have to say this is incredibly straight forward. You can encapsulate the creation logic into a constructor which simplifies the process:
-- Constructor function Greeting:new(o) o = o or {} o.__index = self return setmetatable(o, o) end lolcat = Greeting:new{ hello = 'hai' } -- https://github.com/silentbicycle/lunatest assert_equal('hai', lolcat.hello)
Although prototyping still presents a mental shift for me the Lua approach feels much cleaner and simpler. I find the dot/colon approach (mentioned above) much cleaner as well.