lua-users home
lua-l archive

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

> On Jun 27, 2016, at 6:51 PM, Jay <> wrote:
> What if the __len value of the metatable of a table was used as the value of the length and tables have a default metatable that causes `t.n` to trigger __len, essentially making it the same as `#t`? Furthermore, it would work in the opposite way, where changing the value associated with the 'n' key would change __len, causing #t to change as well. Functions such as table.insert could increment the value of t.n and table.remove could decrement this value. (Or we could have table.set and table.add so that the user could choose whether or not to manipulate array length). Pairs would go unharmed as it wouldn't actually be a key in the table, just handled by the metatable.

To be honest I’ve never liked the use of “n” as a pseudo-length. First, it’s inconsistent (collides with use of #). Second, it’s hi-jacking a perfectly normal user key with very little notice (why wasn’t a reserved “_N” used?). Finally, it makes the length second-class. Yes, in some cases it’s nice that a shallow copy of an array also copies the length, but there are other cases where this either fails or isn’t desired (consider an algorithm to only copies the array part .. oops!). In addition, wiring up “n” to metamethods is messy, since it’s already a candidate for __newindex etc, and if you suddenly add __len into the equation the logic is going to get byzantine quickly.

The only good argument I’ve seen for using “n” over a first-class length (that is, being able to assign to #t) is that space is only allocated for the length when it’s needed. However, I just ran a crude benchmark and (on a 64-bit Mac) Lua seems to be allocating 82 bytes of space for an empty table, so adding 8 bytes per table (for the length) isn’t much, and might even be free since most heap allocators round allocations up to multiples of 16 bytes or more these days anyway.

My personal feeling is that we need a first-class explicitly set length. If this isn’t set for a given table (is nil), then Lua uses current # behavior, as do things like table.pack(). If the length IS set explicitly, then # simply returns this value, and library functions just the length in ways that make sense (e.g. when appending an item to the end of an array). Even this has issues: how do you check to see if the length is set (you can’t use $t)? And perhaps in Lua 6.0 the old behavior is retired (along, probably, with me <grin>).