lua-users home
lua-l archive

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


What if you want to wrap the returned table with another metatable?

On Tue, Jul 26, 2016 at 6:23 AM, Coda Highland <chighland@gmail.com> wrote:
On Mon, Jul 25, 2016 at 8:34 PM, Rodrigo Azevedo <rodrigoams@gmail.com> wrote:
>> So you can essentially choose between warts, garbage factory, or space
>> hog.  The current choice of Lua/table.pack is warts.
>
>
> Let's try:
>
> 0) define __something as "reserved" words.
>
> 1) Define the table as its own "metatable" by default, namely, search for
> __something when appropriate and fallback to the one defined by
> setmetatable() (standard behavior) (why not?)
>
> change the manual from
>
> rawget(getmetatable(o) or {}, "__ev")
>
> to
>
> (type(o) == 'table' and rawget(o,"__ev")) or rawget(getmetatable(o) or {},
> "__ev")
>
> 2) Define __len to accept integers >= 0 OR a function() OR a table. If
> integer >=0 then O(1) # "by definition".
>
> We are assuming 0) and 1) and 2) thereafter
>
> 3) Define table.pack() as the default "stack mirror", and (automatically)
> embed an additional  __newindex to update __len when appropriate.
> table.unpack(), with a defined # (__len), just is a "stack mirror".
>
> I think that pack() and unpack() are used mainly with "the stack" or known
> sequences that almost don't change, and consequently do not trigger
> __newindex, implying almost no overhead.
>
> 4) For the rare occasions that you do not want a sequence from table.pack()
> just do t.__len = nil t.__newindex = nil.
>
> Then,
>
> a) # will be (more) useful since
> b) every other table.something() will function as expected with no extra
> (meta)table required or GC work and __len is much better (and a "reserved"
> word) than .n .
> c) use table.(un)pack as the default to (un)pack (to)from "the stack" and
> leave { } for the cases that you known it is appropriate.
>
> side-effect: we have a standard (and a bit faster, since we do not need to
> getmetatable everywhere) "unbounded array" constructor
> a = table.pack()
> with well defined length and compatible with the stack.
>
> Is this possible?
>
> --
> Rodrigo Azevedo Moreira da Silva

I like the way you're thinking, and that metatable design would quite
simplify things for a lot of common cases (assigning a table as its
own metatable is something I used to do rather often).

I'm still pondering over the potential breakages this could introduce
for 5.3 code being promoted to this hypothetical 5.4 design. It
doesn't SEEM like it would break things very much outside of code that
uses table.pack (and a hypothetical compat flag could have table.pack
set both .n and .__len), and the fix for more generic code that does
happen to be affected would be easy (setmetatable to nil).

Unfortunately, the downside I see is that there are cases where
metatables are only checked at time of assignment for the purposes of
optimization, which makes this... well, not BAD, because existing code
won't break, but it would mean that some metamethods still require
jumping through the whole metatable hoop while others can be assigned
in-place. The question this raises is: Is this a bigger caveat than
the current one, or a smaller one?

/s/ Adam