Thomas W
Thomas W

Reputation: 15391

Might Lua's length operator return a negative index?

The, well, special specification of Lua's length operator made me wonder whether Lua would be "allowed" to return a negative value in a situation like

#{[-5]=1,[-1]=3}

It says:

The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil;

n=-5 and n=-1 would meet this criterion in my example, right?

moreover, if t[1] is nil, n can be zero.

Right, it can be zero, but it's not guaranteed, right?

For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value.

This isn't the case here, so it doesn't apply.

If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).

This is the case here, so again, n=-5 and n=-1 would be valid return values, right?

Can I be entirely certain that Lua always returns 0 for the example table, or any other table containing only negative indices? If (hypothetically) I'd be writing a Lua interpreter and would return either of those values, would I be conforming with the specifications?

Edit

Obviously, the way Lua is implemented, it does not return negative values. I felt the length operator is somewhat underdocumented and I see that Lua 5.2's documentation has changed. It now says:

Unless a __len metamethod is given, the length of a table t is only defined if the table is a sequence, that is, the set of its positive numeric keys is equal to {1..n} for some integer n. In that case, n is its length. Note that a table like

  {10, 20, nil, 40}

is not a sequence, because it has the key 4 but does not have the key 3.

So, it now talks about positive numeric keys, that's much clearer. I'm left wiser but not totally happy with the documentation. When it says the "length is only defined if the table is a sequence", it should also state that even if the table is not a sequence a value is returned, but the behavior is undefined. Also, this table looks pretty much like a sequence:

a = setmetatable(
  {0},
  {
    __index = function(t,k)
      return k < 10 and k or nil 
    end
  }
)
i = 1
while a[i] do
  print(a[i])
  i = i+1
end
--[[ prints:
0
2
3
4
5
6
7
8
9
]]
print(#a)
-- prints: 1

However, this is becoming nitpicking as it's pretty clear that it wouldn't make sense to take into account what mess __index might make. And Stackoverflow is certainly not the place to complain about documentation that could be more precise.

Upvotes: 3

Views: 732

Answers (2)

Charles Stewart
Charles Stewart

Reputation: 11837

As you have noted, the specification of the length operator has changed between 5.1 and 5.2.

Can I be entirely certain that Lua always returns 0 for the example table, or any other table containing only negative indices?

You can for the current reference implementation, which ensures that for ilen defined

function ilen (xs) 
    local i=0
    while xs[i+1] do i=i+1 end
    return i 
end

we always have #xs >= ilen(xs) - see the definition of luaH_getn in the ltable.c source. But the specification now deliberately does not promise this behaviour: a conformant implementation can return nil or raise an exception for attempts to find the length of tables that are not sequences.

Upvotes: 1

Zeddy
Zeddy

Reputation: 2089

From the text in reference link. The answer is NO.

I think your confusing the fact that if a NIL is found then the length of the table is deemed to be position the NIL was found -1.

Therefore if t(1) is NIL then 1 - 1 = 0 so the table length is 0.

If the length of a table was 5 then the next position or t(6) IS or WOULD BE NIL

The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, n can be zero.

Upvotes: 0

Related Questions