lua-users home
lua-l archive

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


A while back Luiz Henrique and I brainstormed potential support for multi-index tables in Lua. The motivation was the binding multi-index C structures to Lua. Here is a summary of our conversation.

Currently, we either use t[i][j][k] ou t(i,j,k). Besides the strange syntax, t(i,j,k), is not an l-value. On the other hand, t[i][j][k] requires that t[i] and t[i][j] be collectable values, since there is no place to store necessary information in a simple type.

We explored using a new syntax t[i,j,k] instead, but in a way that preserves compatibility. The trick is that the number of indices would be defined at compile time.
In other words, t[f()] is always a single-index access, even when f() returns multiple values. t[f(),g()] is always a 2-index access, and so on. In this way, the comma plays a role similar to the comma in loops like "for i = a,b,c". Such loops don't work with "for i = f()", even if f() returns "a, b, c".

The immediate consequence is that t[f()], which is currently adjusted to one return, would never become a multi-index access based on the number of values f() returns. Furthermore, an access with a comma, like t[f(),g()] is already a syntax error today. So things don't get mixed up.

The access would be via __index and __newindex, like today. These methods would receive not just one index, but all indices that were present. In default, they would behave something like this:

__index = function(t, i, ...)
    assert(select('#', ...) == 0, "too many indices")
    return rawget(t, i)
end

__newindex = function(t, i, v, ...)
    assert(select('#', ...) == 0, "too many indices")
    rawset(t, i, v)
end

If we didn't care about compatibility, __newindex would receive the value before the indices. For compatibility, we have to keep the first index, then the value, then the remaining indices. It's not the end of the world.

The metamethods can do whatever they want with the '...'. The behavior is the same when there already exists an entry in the table with a single index, but there should never "already exist" a multi-index entry in a table.

If t is a userdata, it is trivial to use this to make a multi-index access that does not tax the garbage collector.  If t is a Lua table, we can linearize the indices and implement a sparse matrix using a single table without using a proxy.

Anyway, it's an idea I'd like to register here for future reference.