Why isn't my LUA interpreter able to handle string key values?

641 Views Asked by At

When testing code with both a predefined script and the LUA runtime environment, LUA will not take any form of string key values. However, if a numerical value key is used LUA will work with it as intended. The exception to this rule when I am using Tshark with a LUA file to parse packet captures. This allows the string key value syntax to work normally. Is there something I may be performing wrong?

I have tried creating several .lua script files with different variations including:

testArray.NewItem = "value1" testArray["NewItem"] = "value1"

NewItemValue = "NewItem" testArray[NewItemValue] = "value1"

These all result in an nil value or an error due to trying to call a nil value depending on the return style used to check.

> tcpstream = {}
> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil
> tcpstream[1] = "nothing"
> print(#tcpstream)
1
> print(tcpstream[1])
nothing

the output of the print(#tcpstream) after the tcpstream[stream1] = "nothing" should show 1 not zero. The subsequent print(tcpstream[1]) should also show "nothing".

2

There are 2 best solutions below

1
Brad Pitt On

From http://lua-users.org/wiki/TablesTutorial

The # operator doesn't count all the items in the table (!). Instead it finds the last integer (non-fractional number) key. Because of how it's implemented its results are undefined if all the integer keys in the table aren't consecutive. Which is why it shouldn't be used for tables used as sparse arrays[2]).

The '#' is not a good(sometimes not correct) way to count the number of elements in Lua table.

As for

> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil

Lua uses key,value pairs, not explicitly index. If you do 'arr[1] = 22', it means the value for the key '1' is 22, not the value for the first element is 22.

4
Nifim On

The length operator(#) does not work as you believe, this is a common mistake for beginners in Lua.

The default behavior for #sometable is to return the number of consecutive key starting at the number 1(or after any nil value for 5.3). String keys are never evaluated with the default # operator for a table.

In 5.3 if your sequence contains multiple nil values the behavior of # is non-deterministic.

Lua 5.3 Reference Manual: 3.4.7 – The Length Operator

Lua 5.1 Reference Manual: 2.5.5 – The Length Operator

I will include the lines from 5.1 as i feel it covers the information regarding the operator and tables well. While note identical to how 5.3 work it maybe easier to understand why you see the behavior you do.

2.5.5 – The Length Operator The length operator is denoted by the unary operator #. The length of a string is its number of bytes (that is, the usual meaning of string length when each character is one byte).

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 t1 is nil, n can be zero. 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. 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).

Here are some examples of different table and their # results:

table1 = { --number keys in array
  true,
  true,
  true,
}
table2 = { -- number keys in hash
  [1] = true,
  [2] = true,
  [3] = true,
}
table3 = { -- only strings as key
  ['1'] = true,
  ['2'] = true,
  ['3'] = true,
}
table4 = { -- No key 2 defined
  [1] = true,
  -- [2] = true, 
  [3] = true,
}
table5 = { -- table with both string and number keys
  [1] = true,
  ['2'] = true,
}
print(#table1) -- 3
print(#table2) -- 3
print(#table3) -- 0
print(#table4) -- v5.3(1 or 3) v5.1(1)
print(#table5) -- 1