The “Seven Languages” books (and probably all of the “Seven in Seven Weeks” series) is more a collection of amuse bouche (amuse bouches? amuses bouche? amusi bouchi? nahh) than of entrees or even appetizers. And that makes sense because there’s no way to fit all the details on seven languages in one book. But it also means you read a section and find yourself going “What the heck was that? It was really tasty, but I really want more.”
So it was when I read the section on metatables. Sure there is some info on metatables in Seven More Languages but I really wanted more. I found the Lua book at http://www.lua.org/pil/13.html to be very useful in augmenting it. All of chapter 13 is devoted to metatables and metamethods. I also figured out why the object-oriented stuff got put in Day 2.
So, metatables!
The Amuse Bouche
All tables have metatables, but by default the metatables are empty. You can get to a metatable for a table using getmetatable(sometable) . And, hopefully not surprisingly, you can change a metatable for a table using setmetatable(table, new_metatable) .
So, how do you create a new metatable? And what can go there?
Recall the Florida info table:
stateFL = { capital = 'Tallahassee', bird = 'mockingbird', population = 19890000 }
Trying to print it just gives its address, as is done in many languages.
> print(stateFL) table: 0050D708
But you can create a function to convert the table to a proper string:
function to_string(t) local result = {} for k, v in pairs(t) do result[#result + 1] = k .. ": " .. v end return table.concat(result, "\n") end
Of course, you could just print the table using this new function print(to_string(stateFL)) but that’s not noteworthy. Instead, assign the __tostring function of the metatable. One way to do this is to create a metatable with the function as its only member and make it the metatable of stateFL
mt = { __tostring = to_string } setmetatable(stateFL, mt)
Then printing the table does the expected thing:
> print(stateFL) bird: mockingbird capital: Tallahassee population: 19890000
There are lots of operators which can be overriden using metatables, including +, -, /, *, <, <=, and ==. You can also override the action when reading and writing to the table to provide different default values, tracking of all changes to the table, and read only tables.
Even though Lua has a mechanism for object oriented programming, you can use metatables to quickly create classes. The Lua book on-line shows how to create a Set class with just metatables. I’ve got a copy in the file Set.lua on my Github account.
The Set class is pretty cool and it points out another feature of Lua, that it’s a prototype rather than object oriented language. Since the first book covered Io, another prototype language, that’s not a new idea for me, but I’ll still finish up day 2 with finding out how Lua handles prototyping.
Leave a Reply