lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


steve donovan wrote:
Hi guys,

Any Lua type can have a metatable (apart from userdata and tables) but
it applies to every instance of that type. This is very useful (e.g.
allowing things like s:sub(1,-2)) but sometimes it would be very
_cool_ if individual functions could have their own metatable.  It
would make for a more polymorphic way of doing things. For instance,
in PL the functions creating sequences return functions, so that they
are immediately consumable by for loops, etc.  To chain methods
operating on sequences, it's necessary to create a wrapper object
explicitly.  Now this wrapper object defines __call appropriately, so
the result is still callable ('functors'). This tends to be the
recommended practice, but one takes a performance hit for this.

Metatables for individual functions would allow method chains
operating on functions. So the question is, what are the performance
implications of such a feature?

steve d.


Hi Steve,

You could of course borrow the following trick from PIL's section on weak tables:

local func_meta = { }
setmetatable(func_meta, { __mode = "k" })

function setfmeta(func, meta)
   func_meta[func] = meta
   return func
end

function getfmeta(func)
   return func_meta[func]
end

then if you want, you can override the native:

-- upval access is faster than global lookup
local type = type
local setfmeta, getfmeta = setfmeta, getfmeta
local setmeta, getmeta = setmetatable, getmetatable

function setmetatable(that, meta)
   if type(that) == "function" then
      return setfmeta(that, meta)
   end
   return setmeta(that, meta)
end

function getmetatable(that)
   if type(that) == "function" then
      return getfmeta(that)
   end
   return getmeta(that)
end

This is obviously going to be more expensive than the native {get,set}metatable but I've found function calls, string comparison and table indexing in Lua to all be pretty low cost compared the other dynamic languages (Perl, Ruby, etc.), so for my purposes at least, it's negligible.


Cheers,
Rich