user2276872
user2276872

Reputation:

Operator # nil values at end of array

I use:

b.x = {}
a = Obj()
a:AddParams("a", "b", "c")

...
...

function Obj:AddParams(a, b, c, d, e)
  table.insert(b.x, {["one"] = a, ["two"] = b, ["three"] = c, ["four"] = d, ["five"] = e})
end

and then I print #b.x and it prints 1. Shouldn't it print 2 since # operator counts nil values and I only give the first 3 parametrers on a:AddParams, leaving the last two nil? Thanks a lot

Upvotes: 0

Views: 570

Answers (3)

Amber
Amber

Reputation: 526543

Now that you've clarified what your code is doing:

b.x actually winds up being a one element table for which the single element is another table due to how your code calls table.insert:

b.x = {

  [1] = {                          <======= this single element in the top-level
    ["one"] = "a",                          b.x table is what the # operator counts
    ["two"] = "b",                          when you apply it as #b.x
    ["three"] = "c"
  }

}

Thus, calling #b.x will always return 1 no matter what you pass to your function, because you're always adding that table as a single element in the originally empty table you initialize b.x to be.

Note however that even if you didn't create this nested table, the value returned from # still wouldn't be what you're expecting. The # operator does not count nil values. What the # operator counts is the length of the sequential numerical indices of a table starting at 1 (and is not defined for tables with non-sequential numerical indices). Thus,

  • #{ [1]="a", [2]="a" } evaluates to 2
  • #{ [1]="a", [3]="a" } is not defined by the Lua standard, because of non-sequential indices
  • #{ [1]="a", ["two"]="b" } evaluates to 1 (because "two" isn't a number, it's a string).

Previous answer...

Not sure where you're getting 1 from:

> a = {}
> a[1] = "a"
> a[2] = "b"
> a[3] = "c"
> a[4] = nil
> a[5] = nil
> print(#a)
3

(Note that assigning nil as a value at the end of a table does nothing - you'd get the same result omitting the a[4] and a[5] lines.)

Did you perhaps actually skip a[2]? That would result in #a being 1, since it only counts contiguous items starting from index 1.

Upvotes: 1

legends2k
legends2k

Reputation: 32884

Shouldn't it print 2 since # operator counts nil values

No, exactly the opposite!

First of all, the whole notion of adding a nil to a table is invalid. You can store anything in a table except nil. Doing so simple deletes the value already present in that key (index) but doesn't insert a nil inside. It's like the mathematical null set ∅ which is used to denote emptiness as an entity but is not a tangible value/object. Accessing any index not present in the table would give you nil, you don't have to insert one to see them being there; any non-existent key has the value nil denoting that the value isn't there.

> a = { }
> print(a[1])
nil
> a = { "abc" }
> print(a[1])
abc
> a[1] = nil   -- this is just erasing 'abc' from the table; not add/insert nil
> print(a[1])
> nil

Thus they never constitute towards the size of the table.

The length operator returns, n, the count of the elements in a sequence; a sequence is a table with values (non-nil of course - which is implied since one can never insert a nil as noted above) indexed by contiguous integers starting from 1 extending to some positive integer n. If they aren't continuous (broken with holes) then the operator # shouldn't be used. The Lua manual specifically calls out that using # is defined only if a table is a sequence. However, note that non-integer keys have no bearing on the sequence nature of the table.

Upvotes: 1

Tom Blodget
Tom Blodget

Reputation: 20772

You are constructing a table and inserting it into an empty table with key 1. If you want to insert multiple elements, you have to call insert for each one.

And, the table you are constructing has string keys, which don't influence # at all.

I suggest you use an IDE with a debugger. See that [lua] tag wiki.

Upvotes: 0

Related Questions