Re:Tables
by Dylan16807 on Thursday September 13, 2018 @12:02AM
(#17975906)
I would argue that the length semantics are mostly unrelated to the hybrid array/hash nature. You could have the same problems on an array-only data structure, and you can invent semantics that avoid them without significantly changing the data structure.
In this way Lua already optimizes the array use case naturally. It never tries to infer whether a table is supposed to have array semantics or hash semantics. You can use a table as a hash, as an array, or (commonly) as both.
The cost of this simplicity and concision is born by the semantics of the length operator (#). The default __len metamethod on a table does a binary search looking for the first missing positive integer key, the boundary that marks the end of a logical array. The binary search will work even if your integer keys have spilled over into the hash part, though it works much faster if it doesn't have to inspect the hash part.
This why in Lua your arrays can't have holes (non-sequential positive integer keys), at least not if you want #t to behave as expected. Lua has no way of knowing the size of your array otherwise, at least not for plain tables lacking user-defined metamethods.
That said, there's a convention that uses the string key "n" to record the intended length. For example, table.pack() assigns the argument list to a table and sets "n" to the number of arguments. It does this because a nil argument value would create a hole. Also, since Lua 5.3 you can overload the __len metamethod, which could simply return t.n. Similarly, you can overload the __index and __newindex metamethods so that insertions update t.n or some other marker.
FWIW, I've tried hard not to express any value judgments in the above description. I've also deliberately abstained from discussing array-related language proposals.