  lua-l archive

• Subject: Re: Deprecate "Attempt to index a nil value" error; instead, return nil or create table
• From: Philippe Verdy <verdyp@...>
• Date: Tue, 3 Mar 2020 15:37:18 +0100

```Le mar. 3 mars 2020 à 12:53, Anton Jordaan <anton.jordaan@sylvean.com> a écrit :
> a,b,c,d,e can be any valid table indices.  I assume you meant "what if
> t[a][b] doesn't respond to __newindex"?
>
> Since t[a][b][c][d][e] = v is simply syntactic sugar,

This is completely false. The real meaning is in fact much like:
local _ref; _ref = t[a]; _ref = _ref[b]; _ref = _ref[c]; _ref =
_ref[d]; _ref[e] = v

Or better:
local _ref1 = t.__getindex(a)
local _ref2 = _ref1.__getindex(b)
local _ref3 = _ref2.__getindex(c)
local _ref4 = _ref3.__getindex(d)
_ref4._setindex(e, v)*

Note that there are references to *different* table objects and that
the syntax t[a][b][c][d][e] is not a single table indexing but
multiple indexings, with all but the last one being dereferenced by
This is not really a multidimensional table. but a table of tables of tables....

If you want to create a single multidimendional table "t", what you
would need in Lua would be to use a syntax like
t[mykey(a, b, c, d, e)] = v
by using some companion function to compute a key. That function could
be a metaproperty of the table, stored for example in its metatable.
getmetatable(t)['__setindex']( [getmetatable(t)['mykey'](a, b, c, d, e)], v)

The current syntax t[a][b][c][d][e] however does not assume the
existence of any custom multidimenional indexing function; so all
tables in Lua are strictly unidimensional, and this syntax then
implies the creation of multiple table objects (one for each plane,
one for each row in each plane, onde of each column in each row in
each plane, etc.). This is clearly inefficient for multidimensional
tables (this is also true for Java or Javascript).

The same syntax in C or C++ however may be efficient if each dimension
is a positive integer in a compact range (from 0 to n-1) whose
cardinality is static and predeclared as part of the type, because it
does not imply any creation of subtable objects to hold extra table
pointers (or pointers and references in C++). When the dimensions are
not constrained, C and C++ also require the use of multiple tables. So
the syntax becomes inefficient as well.

The technic is then to have tables having multi-key indexing. As Lua
has a single key indexing, you have to create it yourself.

What would be good in Lua is to allwo this syntax
t[a, b, c, d, e]  for a single table with multi-key indexing
t[a][b][c][d][e] for multiple tables with unikey indexing

This technically would require a the multidimensional multikey
indexing function that would create a indexable unique reference that
can be used as the single key in the existing unidimensional Lua
table, both for reading and writing in that multidimensional table. It
is posible to do that by extending the "__getindex", "__setindex"
metafunctions so they accept more than one "index" parameter.
Internally that metafunction may need an internal table to keep a
dictionary of used multidimensional indexes and infer an
unidimensional index position, but this is not always the case (e.g.
when all dimensions are unconstrained ranges but are all integers, you
can interleave the bits in each dimension to create a single integer
value from multiple ones, but the classic multidimensional arrays of
C/C++ use a simple multiplication of each key by a static
cardinal.before adding them, and this is much faster than bit
interleaving (used for example in geographic databases for indexing