What does # mean in Lua? - lua

I have seen the hash character '#' being added to the front of variables a lot in Lua.
What does it do?
EXAMPLE
-- sort AIs in currentlevel
table.sort(level.ais, function(a,b) return a.y < b.y end)
local curAIIndex = 1
local maxAIIndex = #level.ais
for i = 1,#currentLevel+maxAIIndex do
if level.ais[curAIIndex].y+sprites.monster:getHeight() < currentLevel[i].lowerY then
table.insert(currentLevel, i, level.ais[curAIIndex])
curAIIndex = curAIIndex + 1
if curAIIndex > maxAIIndex then
break
end
end
end
Apologies if this has already been asked, I've searched around on the internet a lot but I haven't seem to have found an answer. Thanks in advance!

That is 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 t[1] 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).

# is the lua length operator which works on strings or on table arrays
Examples:
print(#"abcdef") -- Prints 6
print(#{"a", "b", "c", 88}) -- Prints 4
-- Counting table elements is not suppoerted:
print(#{["a"]=1, ["b"]=9}) -- # Prints 0

#is most often used to get the range of a table. For example:
local users = {"Grace", "Peter", "Alice"}
local num_users = #users
print("There is a total of ".. num_users)
Output:
3

Related

[lua]: Key with value 1 doesnt do the same as regular 1

Ive been coding for a mod Im making for a game but I ran into an issue with tables not returning values when the key is entered:
for k, v in pairs(self.math) do
print(self.exce[1])
print(self.exce[k])
print(k)
if self.exce[k] ~= nil then
self.math[k] = nil
end
end
This is the specific part of the script that is breaking. When I run these in the game it returns:
[lua]: true
[lua]: nil
[lua]: 1
Which means is basically saying that 1 is not equal to 1.
The function I used to store my data is
function filterExceptions.server_onException( self, id )
if self.exce[id] == nil then
self.exce[id] = true
self.network:sendToClients( "client_onList", id )
else
self.exce[id] = true
self.network:sendToClients( "client_offList", id )
end
end
In this code the self is a table made by the game you can acces and get game data from or store it in and the id comes from a function I made to get the players id. This id in this case is a 1 (I printed it multiple times).I know that every part of this code is working except for the code in the first block, and escpecialy the part where it tries to do self.exce[k]. Ive tried a lot like going trough every variable in self.exce to see if it was in there and then do stuff, but it still wouldn't work. Its very annoying how lua thinks that k ~= 1 while it definitely is, ive even used similar code in a part that is working.
So what is wrong about this code that its not printing the self.exce[k] while self.exce[1] does work? Dont worry about the creation of the table and stuff, cuz that is already happening whenever it is needed, else it would have given errors about that too.
Putting together a couple different comments and your code here, it looks like the index value of the array in some particular iteration of the "for in pairs" loop (or perhaps all of them, but I'll touch on that in a minute) is a string instead of an integer.
To summarize if you don't want to read the entire thing, "for k, v in pairs" loops will iterate through an entire array, setting k to the index of the value v. It appears your "for in pairs" loop is attempting to iterate through a value of nil where k is a string instead of an integer. You may also want to look into using ipairs instead of pairs in your for loop.
The value of someArray[1]is different than the value of someArray["1"].
The index [1] is a completely different index than the index ["1"] for any given array.
A simple fix would be to use
ind = tonumber(k)
print(self.exce[ind])
This converts the string k to a number type. Be aware this may throw an error if k is a non-numerical string. If the array has any values where the index is a non-numerical string, you may get an error. As the other answer suggests, converting the index k to a string instead of an integer would work as well, and would not throw errors if you used a non-numerical value for your indices.
My guess as to why this is happening would be that the function that you're using to store your data to an array, filterExceptions.server_onException( self, id ), is being passed a string instead of an integer, which would result in the k value being set to a string in that particular iteration of the "for in pairs" loop.
To help better understand this, here's a bit of example code:
a = {true, false, false}
a[1] = true
a["1"] = true
print("Raw for in pairs loop")
for k, v in pairs (a) do
print(type(k)..k)
end
print("For in pairs converting k to a number")
for k, v in pairs (a) do
ind = tonumber(k)
print(type(ind)..ind)
end
print("For in ipairs")
--which I'm not sure I completely understand but
--it seems to skip over any iteration where k is not a number
for k, v in ipairs(a) do
print(type(k)..k)
end
This code produces the following output:
Raw for in pairs loop
number1
number2
number3
string1
For in pairs converting k to a number
number1
number2
number3
number1
For in ipairs
number1
number2
number3
EDIT: Not sure what's going on in the self.math table so I can't comment on that.
EDIT2: I'd also refer you to the following link: lua: iterate through all pairs in table
The top answer there should help understand the difference between pairs and ipairs, if you don't already. You may want to use ipairs to prevent values of k where v == nil from being iterated through with pairs. pairs will iterate through every key/value pair, whereas ipairs will iterate through integer keys starting at 1 and going until it hits a nil value.
EDIT3: I'm sorry this is such a long answer...I just wanted to be thorough.
It apears converting the id to a string fixes this, tough im still confused as to why this same code worked on another block and not this one.
function filterExceptions.server_onException( self, id )
local id2 = tostring(id)
if self.exce[id2] == nil then
self.exce[id2] = true
self.network:sendToClients( "client_onList", id )
else
self.exce[id2] = true
self.network:sendToClients( "client_offList", id )
end
end

Non numeral indeces and the # never counts?

Given a table with mixed indexes like:
table = {
foo = 'bar'
[1] = 'foobar'
}
My question is about the # which gives the last index which is not separate through a gap while iterating through the table.
print(#table)
will give the output 1.
table = {
foo = 'bar',
lol = 'rofl',
[1] = 'some',
[2] = 'thing',
[3] = 'anything',
[4] = 'else'
}
print(#table)
should print 4
Can I be 100% sure that the # will never be distracted by non-numeral indexes?
Are those indexes really unregarded at every time?
Yes, you can count on that (in lua 5.1).
From the lua reference manual:
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 t[1] 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).
lua 5.2 allows for the __len metamethod to operate on tables and that means # can do other things. See #kikito's answer for some examples.
Etan answer is correct, but not complete.
In Lua, if a table's metatable has a __len function, it will control what the # operator spits out. One can define it so that it takes into account the non-array keys.
local mt = {__len = function(tbl)
local len = 0
for _ in pairs(tbl) do len = len + 1 end
return len
end}
This demonstrates the thing:
local t = {1,2,3,4,foo='bar',baz='qux'}
print(#t) -- 4
setmetatable(t, mt)
print(#t) -- 6
If you really want to make sure that you get the "proper" array-like length, you must use rawlen instead:
print(rawlen(t)) -- 4, even with the metatable set
Edit: Note that __len does not work as I mention on Lua 5.1
The only way is to iterate through entries and count them. Iterate with ipair through the item and increment counter then return result.
function tablelength(T)
local count = 0 for _ in pairs(T) do
count = count + 1 end
return count
end
The # operator only work for hash table type.
See: How to get number of entries in a Lua table?

Lua table initialization - what is incorrect here [duplicate]

This question already has an answer here:
lua: iterate through all pairs in table
(1 answer)
Closed 8 years ago.
I am trying to initialize and print a table. It just isnt working. Any idea what is wrong with this code?
--!/usr/bin/env lua
local retv = {}
retv["test"] = 1000
for k,v in ipairs(retv) do
print (k,v)
end
It prints nothing. I am sure I am missing something very basic but I cant figure this out.
There are two forms of the for-loop in Lua:
The numeric and the generic for-loop.
ipairs(t) is an iterator constructor returning up to three arguments suitable for the generic for, allowing you to iterate over the initial sequence (indices 1,2,3,...) in order.
Possible implementations:
function ipairs(t)
local i = 0
return function()
i = i + 1
if t[i] ~= nil then
return i, t[i]
end
end
end
local function ipairs_helper(t, i)
i = i + 1
if t[i] ~= nil then
return i, t[i]
end
end
function ipairs(t)
return ipairs_helper, t, 0
end
As you can see, that will never return your entry with key "test".
What you want instead, is pairs(t), which is equivalent to next, t.
That will iterate all elements.
You need to use pairs instead of ipairs. pairs iterates over all keys, ipairs only iterates over keys that form a sequence of integers starting from 1 without gaps. (Whether these keys are stored in the array or the hash part of the table is an implementation detail and may change during the lifetime of the table.)
For example, ipairs({'a', 'b', nil, 'c'}) iterates over keys 1 and 2, stopping at (and not including) 3, as that key is missing from the table.

Why does Lua's length (#) operator return unexpected values?

Lua has the # operator to compute the "length" of a table being used as an array.
I checked this operator and I am surprised.
This is code, that I let run under Lua 5.2.3:
t = {};
t[0] = 1;
t[1] = 2;
print(#t); -- 1 aha lua counts from one
t[2] = 3;
print(#t); -- 2 tree values, but only two are count
t[4] = 3;
print(#t); -- 4 but 3 is mssing?
t[400] = 400;
t[401] = 401;
print(#t); -- still 4, now I am confused?
t2 = {10, 20, nil, 40}
print(#t2); -- 4 but documentations says this is not a sequence?
Can someone explain the rules?
About tables in general
(oh, can't you just give me an array)
In Lua, a table is the single general-purpose data structure. Table keys can be of any type, like number, string, boolean. Only nil keys aren't allowed.
Whether tables can or can't contain nil values is a surprisingly difficult question which I tried to answer in depth here. Let's just assume that setting t[k] = nil should be the observably the same as never setting k at all.
Table construction syntax (like t2 = {10, 20, nil, 40}) is a syntactic sugar for creating a table and then setting its values one by one (in this case: t2 = {}, t2[1] = 10, t2[2] = 20, t2[3] = nil, t2[4] = 40).
Tables as arrays
(oh, from this angle it really looks quite arrayish)
As tables are the only complex data structure in Lua, the language (for convenience) provides some ways for manipulating tables as if they were arrays.
Notably, this includes the length operator (#t) and many standard functions, like table.insert, table.remove, and more.
The behavior of the length operator (and, in consequence, the mentioned utility functions) is only defined for array-like tables with a particular set of keys, so-called sequences.
Quoting the Lua 5.2 Reference manual:
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
As a result, the behavior of calling #t on a table not being a sequence at that time, is undefined.
It means that any result could be expected, including 0, -1, or false, or an error being raised (unrealistic for the sake of backwards compatibility), or even Lua crashing (quite unrealistic).
Indirectly, this means that the behavior of utility functions that expect a sequence is undefined if called with a non-sequence.
Sequences and non-sequences
(it's really not obvious)
So far, we know that using the length operator on tables not being sequences is a bad idea. That means that we should either do that in programs that are written in a particular way, that guarantees that those tables will always be sequences in practice, or, in case we are provided with a table without any assumptions about their content, we should dynamically ensure they are indeed a sequence.
Let's practice. Remember: positive numeric keys have to be in the form {1..n}, e.g. {1}, {1, 2, 3}, {1, 2, 3, 4, 5}, etc.
t = {}
t[1] = 123
t[2] = "bar"
t[3] = 456
Sequence. Easy.
t = {}
t[1] = 123
t[2] = "bar"
t[3] = 456
t[5] = false
Not a sequence. {1, 2, 3, 5} is missing 4.
t = {}
t[1] = 123
t[2] = "bar"
t[3] = 456
t[4] = nil
t[5] = false
Not a sequence. nil values aren't considered part of the table, so again we're missing 4.
t = {}
t[1] = 123
t[2] = "bar"
t[3.14] = 456
t[4] = nil
t[5] = false
Not a sequence. 3.14 is positive, but isn't an integer.
t = {}
t[0] = "foo"
t[1] = 123
t[2] = "bar"
Sequence. 0 isn't counted for the length and utility functions will ignore it, but this is a valid sequence. The definition only gives requirements about positive number keys.
t = {}
t[-1] = "foo"
t[1] = 123
t[2] = "bar"
Sequence. Similar.
t = {}
t[1] = 123
t["bar"] = "foo"
t[2] = "bar"
t[false] = 1
t[3] = 0
Sequence. We don't care about non-numeric keys.
Diving into the implementation
(if you really have to know)
But what happens in C implementation of Lua when we call # on a non-sequence?
Background: Tables in Lua are internally divided into array part and hash part. That's an optimization. Lua tries to avoid allocating memory often, so it pre allocates for the next power of two. That's another optimization.
When the last item in the array part is nil, the result of # is the length of the shortest valid sequence found by binsearching the array part for the first nil-followed key.
When the last item in the array part is not nil AND the hash part is empty, the result of # is the physical length of the array part.
When the last item in the array part is not nil AND the hash part is NOT empty, the result of # is the length of the shortest valid sequence found by binsearching the hash part for for the first nil-followed key (that is such positive integer i that t[i] ~= nil and t[i+1] == nil), assuming that the array part is full of non-nils(!).
So the result of # is almost always the (desired) length of the shortest valid sequence, unless the last element in the array part representing a non-sequence is non-nil. Then, the result is bigger than desired.
Why is that? It seems like yet another optimization (for power-of-two sized arrays). The complexity of # on such tables is O(1), while other variants are O(log(n)).
In Lua only specially formed tables are considered an array. They are not really an array such as what one might consider as an array in the C language. The items are still in a hash table. But the keys are numeric and contiguous from 1 to N. Lua arrays are unit offset, not zero offset.
The bottom line is that if you do not know if the table you have formed meets the Lua criteria for an array then you must count up the items in the table to know the length of the table. That is the only way. Here is a function to do it:
function table_count(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
If you populate a table with the "insert" function used in the manner of the following example, then you will be guaranteed of making an "array" table.
s={}
table.insert(s,[whatever you want to store])
table.insert could be in a loop or called from other places in your code. The point is, if you put items in your table in this way then it will be an array table and you can use the # operator to know how many items are in the table, otherwise you have to count the items.

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.
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.
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.

Resources