lua-users home
lua-l archive

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


Honestly, I had to open up Lua to see if this was true. I had thought that indexing a table with nil was an error. Huh.

> Consequently foo[nil] must resolve to nil because key nil can never be part of the table.

I don't arrive at the same conclusion. An error would be just as, if not more, expected than silently returning nil, since the manual explicitly says you "cannot use nil or NaN as a table index". (Cannot use) ~= error, but it doesn't mean it couldn't be, had the designers decided for that. Since you can NEVER use nil as a table index, using one in your program seems like an obvious error, if my ignorant self were to make a language. As is, you don't know if `t[misspelled_key]` is nil, or if the key is accidentally nil. Of course `t.misspelled_key` and `t["misspelled_key"]` returning `nil` makes 100% sense.

That said, it's too late to change it now (imho). This would be a big breaking change for much code that is already out there.


-- Andrew Starks


On Tue, Jan 17, 2023 at 5:37 AM SH <sebastian.horlebein@gmail.com> wrote:
As already mentioned linters like Luacheck can help with this problem.
Warning 221 Local variable is accessed but never set should save you here.

Alternatively you can use have __index check the key.

local a = setmetatable({}, {__index = function (t, k) if k == nil then error("error table index with nil") end end})
print(a[nil])



Am Di., 17. Jan. 2023 um 12:21 Uhr schrieb Aki Tuomi <cmouse@cmouse.fi>:

> On 01/17/2023 1:17 PM EET Marcus Mason <m4gicks@gmail.com> wrote:
>
>
> > Yet, if we do
> >
> > > foo = {}
> > > foo[nil]
> > nil
>
> > it works. Why? This sounds like this should
> > emit error?
>
> The reason this doesn't emit an error is most likely due to the fact that __index can be called. I have used this in the past when I needed to store values including nil (in a set) by using a sentinel value as the key in the __(new)index method. Remember that a table lookup returning nil means the index is not present in the table so this code isn't all that surprising, even though we know nil will never index a table (directly).
>
> If you are worried about mistyped locals not being caught, you can use a module like strict.lua to forbid undefined global access.
> Luacheck also solves this problem by statically analyzing the source code, which for most things is a better alternative to a runtime guard on the environment.

We already have mistyped locals getting caught, it's more about not catching places where the index key is nil for whatever reason, e.g.

some_module.IDX_NAME

not being defined. I recently ran into this exact use-case. We have tables with numeric indexes (because that's how they come from external data source) and we have a module which defines names for these indexes.

Unfortunately accessing some_module.NO_SUCH_IDX returns nil -> accesses the table with nil -> returns nil, which is allowed for some of the fields in the data, leading into severe head scratching.

Aki