lua-users home
lua-l archive

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




On Fri, Mar 6, 2020 at 8:01 PM Diego Nehab <diego@impa.br> wrote:

I see a couple of competing arguments here.

(1) It may be better to treat t[i,j] as being equivalent to t[i] in the absence of __index/__newindex. Combined with the above discussion about multi-return functions, this would be the most compatible with old code.

(2) Provide a meaningful default implementation for t[i,j] so that Lua has a multidimensional compound data type built in.

I don't think that it's "absolutely useless" without either of these as Egor asserts, but it's certainly inconvenient. At the very least, it would be nice if the table library provided a predefined multi-index metatable you could assign to a table, or a function that returns an empty table already configured with such a metatable.


We have
t(i1, i2, ...) --> getmetatable(t).__call(t, i1, i2, ...)
This is always called.

We are considering something like
t[i1, i2, ...] --> getmetatable(t).__index(t, i1, i2, ...)
t[i1, i2, ...] = v --> getmetatable(t).__newindex(t, v, i1, i2, ...)
They would be incompatible both because of the t[f()] issue, because the parameter order in  __newindex(t, i1, v, i2, ...) is awkward, and because these methods are only called when the table index doesn't exist. 

t[f()] I don't quite understand why it would be an issue at all; as I described earlier, if the default handler just ignores the extra indices it's fine.

The parameter order is awkward, but that's not actually an incompatibility.

I do see the potential issue with the way the methods are called. With my suggested behavior, it only comes up if you have mixed assignments to t[i] and t[i,j] on the same table and the __newindex isn't built to deal with it. I sort of feel like that's a case of "well, then don't do that" -- if you're intending your table to support multi-indexed data, then you shouldn't ever assign data to a publicly-accessible first index, and the failure mode would simply be considered a bug in the code.
 
Should we instead make
t(i1, i2, ...) = v --> getmetatable(t).__lvaluecall(t, v, i1, i2, ...) ?
This solves the l-value problem with the notation, makes  the meaning of t(f()) = v completely obvious, and would always call the metamethod, just like t() currently does.

Since there are no breaking changes involved, anyone would be free to design a multi-index translation scheme and there even could be a predefined implementation as you suggest.

Now, to be fair, independent of multidimensional indexing, this would be a pretty nice thing to have anyway, especially for DSLs. (Though I'd consider __assigncall instead of __lvaluecall unless you have other places I'm not thinking of where Lua has lvalues.)
 
Now if somebody finds a way for __lvaluecall to receive multiple *values* along with multiple indices, we could even have tables that store and return multi-dimensional data.
Not sure how to work this out, but it sure would be cool.

At that point you might as well just promote tuples to a first-class object instead of juggling them implicitly with the varargs syntax. That would solve ALL of the problems.

/s/ Adam