'nil' as an element in a Lua table?
Asked Answered
A

3

5

I wonder if nil is a valid element in a table in Lua.

What I don't understand is

The following code prints 3

t = {1, 2, 3, nil};
print(#t);

But the following prints 4

t = {1, nil, 3, 4};
print(#t);

I don't understand why the two codes output different results.

Appanage answered 15/8, 2018 at 4:28 Comment(2)
Possible duplicate of how to represent nil in a tableOverseas
Use t = table.pack(1, 2, 3, nil) print(t.n).Orella
O
7

What you're experiencing is argument trimming.

Let's run through what you have and explain what's happening when the Lua parses it.

-- T is equal to 1, 2, 3, (NOTHING)
-- Therefore we should trim the nil from the end.
t = {1, 2, 3, nil};

-- T is equal to 1, nil, 3, 4
-- We have something on the end after nil, so we'll count nil as an element.
t = {1, nil, 3, 4};

The same happens in functions, too. Which can be a bit of a hassle, but sometimes handy. Take the following for example:

-- We declare a function with x and y as it's parameters.
-- It expects x and y.
function Vector(x, y) print(x, y); end

-- But... If we add something unexpected:
Vector("x", "y", "Variable");
-- We'll encounter some unexpected behaviour. We have no use for the "Variable" we handed it.
-- So we just wont use it.

Same goes for the other way around. If you hand in a function that requires X, Y, and Z but you hand it X and Y, you'll be passing nil instead of Z.

Refer to this answer here, because you can indeed represent nil within a table using the following:

--  string  int   nil
t = {"var", "1", "nil"};
Overseas answered 15/8, 2018 at 5:53 Comment(2)
Re: second example. "value nil is not considered part of the table." Try for k, v in pairs({1, nil, 3, 4}) do print(k, v) end.Lorylose
Functions are not "declared" as in some languages. This requires a little different thinking. Vector is a variable that, in your code, refers to a function value after executing the first non-comment line of code. A function call has an expression before the parentheses that is evaluated and if—at runtime—it yields a function value, the call is made passing all the arguments. At the call site, there is no intrinsic concept of how many parameters are expected by whatever function value is being called.Lorylose
F
4

The length operator # corresponds to the intuitive notion of length of an array only for sequences, that is, arrays without holes. See the manual.

Frigging answered 15/8, 2018 at 11:40 Comment(1)
And that begin at an index of 1! Which will trip things up if you are a C/C++ coder and when starting to build a table from that side of the API you naively put in the C array index starting at 0 - BTDT - and got the T-shirt... 8-PTasman
W
2

It depends on what you mean by "valid". A key that points to nil is equivalent to that key not being in the table, therefore the infinite number of keys in a table that haven't been assigned to all point to nil. You can certainly treat nil as a valid value if you intend your data structure to work that way.

As lhf said in his answer, the # operator cannot work consistently if nil appears before the last non-nil element in the array. If you intend to treat your table as a sequence (same link that lhf posted), then nil is not a valid array element.

While answered 15/8, 2018 at 17:29 Comment(1)
# works consistently; it's just not always what you expect :-)Frigging

© 2022 - 2024 — McMap. All rights reserved.