lua-users home
lua-l archive

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


One thing I miss in Lua 5 compared to Lua 4 is the ability to change the
default behaviour of tables. In Lua 4 one could use tag methods to do
this, because one could change the tag methods of type({}), but Lua 5
has a default metatable of nil, so there are no default metamethods for
tables and userdata.

However a small change to lapi.c permits this:

lapi.c:539 says

  if (mt == NULL || mt == hvalue(defaultmeta(L)))
    res = 0;

and if one removes the second part of the test, then the value of
defaultmeta(L) is returned when one calls getmetatable({}). Then one can
set default metamethods.

Is there some reason why this isn't currently allowed? Indeed, the fact
that there *is* a default metamethod table seems to be a trick to simplify
the implementation at the moment, as it isn't documented, and the relevant
lua_State struct member is called _defaultmeta (i.e. it starts with a _,
so is private).

There's one obvious problem with the current scheme: _defaultmeta is also
used for userdata, and in keeping with Lua's treatment of userdata it
would seem better not to allow the default metamethods for userdata to be
changed by user programs. But it is useful to allow the default
metamethods for tables to be changed; for example, I used to use the
concat tagmethod in Lua 4 to do list concatenation, and the unm tagmethod
to do list reversal.

Making this change will break code that tries to tell whether a table is
"vanilla" by testing to see if it has a metatable. But is there a good
reason to do this? The change won't break metamethod chaining (see if
there's a metatable, and if so, see if there's a metamethod, and if so,
call it).

Similarly, the ability to set default metamethods is a potential security
problem, but you can just set make L._defaultmeta a protected metatable
before you run any code, and then it can't be changed.

What am I missing?

-- 
http://www.mupsych.org/~rrt/ | maximiste, n.  pessimiste (Roux)