lua-users home
lua-l archive

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


On Mon, Dec 07, 2009 at 09:06:38AM +0100, spir wrote:
> just to check I'm not overlooking some obvious point. It's certainly trivial, but sometimes I need to be sure.
> 
> * Say an "object"'s metatable __index field points to a "type". The object will not "inherit" the type's metatable (eg the __tostring field). Meaning print(object) will not use the func pointed by the type's metatable __tostring field. We need to transmit the whole of the type's metatable to instance objects.

Say you set the metatable of o to M, and that M itself has a metatable
MM. Suppose also that rawget(M, '__tostring') is nil, but that
rawget(MM, '__tostring') is a function S. So S will be used then
printing out M.

None of this yet guarantees that getmetatable(o).__tostring, that is,
that M.__tostring, is S. You could achieve that by setting M's
metatable's __index field to M's metatable.

But the Lua source seems to use raw lookups for most or all of its
handling of special metafields. So merely getting
getmetatable(o).__tostring to be S (via indirect lookups) won't make S be used when printing
out o.

Is that clear? See:

> o,M,MM = {},{},{}
> setmetatable(o,M); setmetatable(M,MM)
> function S(self) return "S" end; MM.__tostring = S
> print(M)
S
> MM.__index = MM
> return getmetatable(o).__tostring == S
true
> print(o)
table: 0xad8030

> * The only way to transmit a metatable is to explicitely set the original table's one to the new table. (setmetatable(t2, getmetatable(t1)).

For tables, yes. If t1 and t2 are userdata generated by newproxy, then you can create t2
with newproxy(t1), and it will then be assigned the same metatable as
t1. You could roll this functionality into your own table constructor
functions, as well. But you're right there's no native way to do this
but the explicit one.

-- 
Jim Pryor
profjim@jimpryor.net