lua-users home
lua-l archive

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


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