lua-users home
lua-l archive

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


On Mon, Jul 25, 2016 at 9:39 PM, Rain Gloom <raingloom42@gmail.com> wrote:
> 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
>>
>
> What if you want to wrap the returned table with another metatable?
>

Then do it. That much won't have changed, and you can have the
metatable's __len read t.__len, just like you could have had it read
t.n before.

/s/ Adam