Wouldn't it be enough to write a function to do this type-checking for you instead of having the language *always* do it? ‣ Doing this would make debugging harder, as error messages wouldn't tell you what's missing, but just that somewhere in the chain of values there's a nil ‣ I assume the additional condition might have a negative impact on performance, though this might be very small and irrelevant ‣ Ruby does this with the safe navigation operator `nil&.do_stuff`; maybe something similar would be a better choice (though I personally don't think it's necessray) You could easily use something like this: local function index(object, idx, ...) if idx then if object[idx] then return index(object, ...) end else return object end end local value = index(some_4d_table, x, 20, z, "foobar") To traverse a list of nested tables until the end of a list of keys or a missing key in some subtable (which would then return nil). Similarly, you could write a function like this to insert missing tables according to a chain of indices: local function insert(object, value, idx, ...) if ... then if not object[idx] then object[idx] = {} end insert(object, value, ...) else object[idx] = value end end insert(some_4d_table, "Hello, World!", 'foo', 'bar', 'baz', 'message') On 28/02/2020 22:59, Anton Jordaan wrote: > Lua is memory efficient for huge but sparse multi-dimensional arrays, > since nil values aren't stored in the tables. > > However, reading and writing to such sparse multi-dimensional arrays > can be quite a hassle. If I want to access the value of > t[a][b][c][d][e], I first have to check whether t[a] is a table, > t[a][b] is a table, t[a][b][c] is a table etc, otherwise Lua throws an > error "Attempt to index a nil value". > > > For example, to read the value at t[a][b][c][d][e], I cannot simply use: > v = t[a][b][c][d][e] > Instead, the code must look something like: > v = t and t[a] and t[a][b] and t[a][b][c] and t[a][b][c][d] and > t[a][b][c][d][e] > > > Or, to write a value to t[a][b][c][d][e], I cannot simply use: > t[a][b][c][d][e] = v > > Instead, the code must look something like: > > if not t then t = {[a] = {[b] = {[c] = {[d] = {[e] = v}}}}} > elseif not t[a] then t[a] = {[b] = {[c] = {[d] = {[e] = v}}}} > elseif not t[a][b] then t[a][b] = {[c] = {[d] = {[e] = v}}} > elseif not t[a][b][c] then t[a][b][c] = {[d] = {[e] = v}} > elseif not t[a][b][c][d] then t[a][b][c][d] = {[e] = v} > else t[a][b][c][d][e] = v > end > > I suggest that it would be more useful -- and more consistent -- if > the "Attempt to index a nil value" error is deprecated and, instead, > the indexing of undefined variables does the following: > > When reading: simply return nil. Given that undefined variables and > non-existent table entries both return nil, I think it would be more > consistent if an attempt to index an undefined variable also simply > returns nil. (The Lua FAQ states that: "In many languages, trying to > access a non-existent key in a list or dictionary causes an exception; > in Lua the result is simply nil. This is unambiguous because nil > cannot be usefully put into tables.") If t is nil, then t[a] should > also simply be nil, as should t[a][b][c][d][e]. > > When writing: automatically assign a single-entry table to each > undefined variable, with the given index the sole entry. For example, > if t is an undefined variable, then t[a] = v would be syntactic sugar > for t = {[a] = v}. Similarly, if t[a][b] is already declared as a > table but t[a][b][c] is nil, then t[a][b][c][d][e] = v would mean > t[a][b][c] = {[d] = {[e] = v}}. > > > -- Anton > >
Attachment:
signature.asc
Description: OpenPGP digital signature