1114 posts
Location
UK
Posted 29 October 2013 - 08:41 AM
How to use tables
(and use them well)
Welcome to this tutorial about using tables. This tutorial is split into parts:
Part I - Creating a table
A table is a list of values, which are all stored under one variable.
In Lua, a table is an associative array, which means that any values stored in one are referenced by a key, which can be a number, string, [acronym='A boolean is a true or false value. eg 5+5=10 == true, 5+5=11 == false']boolean[/acronym] or even another table!
To make a table, simply do this:
local myTable = {}
The variable myTable is now an empty table.Part II - Numbers as keys
If you already have a table, you can insert a value referenced by a number into the table with one of these methods:
-- This...
myTable[1] = "This is item 1 of the table"
-- ... does the same as this
myTable:insert(1, "This is item 1 of the table")
You can then refer to this value as:
print(myTable[1]) -- Prints out "This is item 1 of the table"
You can replace 1 with any number you like, and it will still work. Note that myTable:insert() will shift the positions of the other values in a table, whereas referencing the table directly (myTable[1] = "…") will overwrite the value at position 1.Part III - Strings as keys
If you are creating an array with no specific order (e.g. a username and password table) you can also use strings as a key:
myTable["ZudoHackz"] = "MyPassword"
myTable["SomeoneElse"] = "SomePassword"
You can't use myTable:insert() with strings (I think). To reference a value, you can just do:
print(myTable["ZudoHackz"])
-- Or
print(myTable.ZudoHackz)
Part IV - Initializing a table with data already in it
local myTable = {}
myTable[1] = "blah1"
myTable[2] = "blah2"
myTable[3] = "blah3"
...
This works, but it is quicker and shorter to do this:
local myTable = {"blah1","blah2","blah3"}
If you create a table like this, myTable[1] would be set to "blah1", myTable[2] would be "blah2" etc.
You can also do this:
myTable = {[1] = "blah1", [2] = "blah2", [3] = "blah3"}
If you do it this way, you can change the order easily:
local myTable = {[3] = "blah1", [2] = "blah2", [1] = "blah3"}
Or even do this:
local myTable = {[1] = "blah1", [6] = "blah2", [300] = "blah3"}
This also works with anything else as a key:
local myTable = {["one"] = "blah1", ["two"] = "blah2", ["three"] = "blah3"}
Part V - Using tables
Tables are used for storing similar information. But, they can also be used for other things, like:
Capturing return values
Some functions, like os.pullEvent() return different amounts of return values. You could do something like this:
local a, b, c, d, e = os.pullEvent()
print(a)
print(B)/>/>/>
print(c)
print(d)
print(e)
but you still can't be sure you have saved all the return values. However, a setup like this:
local myEventData = {os.pullEvent()}
for _, value in pairs(myEventData) do
print(v)
end
would definitely capture all of the values, and definitely return them all. More on the for loop later. Anyway, if you put the function call in curly { } brackets, it will return a table. myEventData[2] in the second example is equal to b in the first example.
Please read
IP.Board screwed up the third line of the first example in this section. It is print b but with brackets, rather than spaces.
This isn't really a use of the table, but it is very useful to learn about
Iterating through a table
With the pairs() function, you can iterate through a table. Here is an example:
local myTable = {"blah1","blah2","blah3"}
for key, value in pairs(myTable) do
print("The value of the key " .. key .. " is ".. value)
end
This piece of code repeats 3 times (there are three values in the table) and prints:
The value of the key 1 is blah1
The value of the key 2 is blah2
The value of the key 3 is blah3
So this can be very useful. How about this?
local myTable = {"blah1","blah2","blah3"}
local function isInTable(table, value)
for _, v in pairs(table) do -- Use _ if you don't need that return value.
if v == value then
return true, k
end
end
return false
end
isInTable(myTable, "blah1") -- Returns [true, 1]
isInTable(myTable, "blah2") -- Returns [true, 2]
isInTable(myTable, "blah3") -- Returns [true, 3]
isInTable(myTable, "blah4") -- Returns false
So iterating through tables is very, very useful.Thank you for reading this tutorial! Please point out any mistakes, and advise me on using tables even better! :)/>/>/>
-Z
7508 posts
Location
Australia
Posted 29 October 2013 - 10:18 AM
There is a lot that you've missed. You haven't pointed out anything such as mixing indexed and key/value elements, negative indexes, iterating through tables, both with a numerical for loop and a generic for loop (pairs/ipairs). The advantages of each type of loop (incremental/ipairs/pairs), especially when dealing with custom indexes such as a table that only contains indexes 1,2,4,17,700. There are various other improvements along these lines that you could make.
I think that maybe explaining and/or showing an example of how tables can help us capture all return results from a function call, or all arguments in a vararg function.
You also don't state why it is better (efficiency-wise and memory-wise) to define the elements in a table when invoking the table constructor. Which I think is needed rather than just stating "but it is quicker and shorter to do this"
Also consider using locals in all your code examples in an attempt to promote good coding habits.
48 posts
Location
France
Posted 29 October 2013 - 10:33 AM
You also don't state why it is better (efficiency-wise and memory-wise) to define the elements in a table when invoking the table constructor. Which I think is needed rather than just stating "but it is quicker and shorter to do this"
I'm relatively new to Lua and may be mistaken about this, but what I've read seems to indicate that the two are completely equivalent:
That is, all tables are created equal; constructors only affect their initialization.
http://www.lua.org/pil/3.6.html
571 posts
Location
Some Fish Bowl in Ohio.
Posted 29 October 2013 - 11:01 AM
It seems like you made this after you told me how to use tables :3. Anyway, nice tutorial, might come in handy sometime.
1583 posts
Location
Germany
Posted 29 October 2013 - 05:39 PM
Good tutorial, but:
local tbl = {["foo"]="bar"}
-------------------------
--This
print(tbl["foo"])
--Is not the same as
print(tbl.foo)
-------------------------
--To do the second type you have to do it like this
local tbl = {foo = "bar"}
print(tbl.foo)
:D/>
892 posts
Location
Where you'd least expect it.
Posted 29 October 2013 - 05:45 PM
Good tutorial, but:
local tbl = {["foo"]="bar"}
-------------------------
--This
print(tbl["foo"])
--Is not the same as
print(tbl.foo)
-------------------------
--To do the second type you have to do it like this
local tbl = {foo = "bar"}
print(tbl.foo)
:D/>
Misinformation.
It works either way.
1583 posts
Location
Germany
Posted 29 October 2013 - 07:31 PM
Good tutorial, but:
local tbl = {["foo"]="bar"}
-------------------------
--This
print(tbl["foo"])
--Is not the same as
print(tbl.foo)
-------------------------
--To do the second type you have to do it like this
local tbl = {foo = "bar"}
print(tbl.foo)
:D/>/>
Misinformation.
It works either way.
o.O
Since when?
I never saw it…
Sorry for the missinformation BTW…
7508 posts
Location
Australia
Posted 29 October 2013 - 07:40 PM
o.O
Since when?
I never saw it…
Since always. The dot notation is just syntactical sugar. The only time it doesn't work is in this case
local t = {["some key"] = true}
print(t.some key) --# this doesn't work, just like the next line doesn't work
t = {some key = true} --# they follow the same rule pattern
7508 posts
Location
Australia
Posted 29 October 2013 - 07:41 PM
o.O
Since when?
I never saw it…
Since always. The dot notation is just syntactical sugar. The only time it doesn't work is in this case
local t = {["some key"] = true}
print(t.some key) --# this doesn't work, just like the next line doesn't work
t = {some key = true} --# they follow the same rule pattern
What you're thinking is that THESE aren't the same
local var = "hello"
local t = {}
t[var] = true --# adds true under the key "hello"
print(t.var) --# looks for a key "var"
which they are not the same.
500 posts
Posted 29 October 2013 - 08:11 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:
myTable[{}] = 5
myTable[true] = 10
7508 posts
Location
Australia
Posted 29 October 2013 - 08:15 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:
myTable[{}] = 5
Of course hoping that you
save the table so that you can access it later!
local k = {}
local t = {[k] = "tables as keys!"}
print(t[k])
500 posts
Posted 29 October 2013 - 08:22 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:
myTable[{}] = 5
Of course hoping that you
save the table so that you can access it later!
local k = {}
local t = {[k] = "tables as keys!"}
print(t[k])
Well, it depends. Let's say you wanted to just make a table of information that your going to return (you're doing this in a function), the end user will use pairs/next to get the values, so there is really no functional purpose in saving them, although it does add to the readability (*wink* :P/> *wink*).
892 posts
Location
Where you'd least expect it.
Posted 29 October 2013 - 09:37 PM
-snip-
Sorry for the misinformation BTW…
It's OK, everyone makes mistakes.
1114 posts
Location
UK
Posted 30 October 2013 - 02:13 AM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:
myTable[{}] = 5
myTable[true] = 10
I put that in the first part.
500 posts
Posted 30 October 2013 - 01:52 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:
myTable[{}] = 5
myTable[true] = 10
Anyway, it is really stupid to use boolean and tables as well.
I hope you were kidding.
758 posts
Location
Budapest, Hungary
Posted 31 October 2013 - 12:46 AM
I put that in the first part. Anyway, it is really stupid to use boolean and tables as well.
Man, that hurt… That was like saying it's stupid to use C++. You can't just go over and state that a bunch of people is stupid, just because they do things you don't.
1114 posts
Location
UK
Posted 31 October 2013 - 04:00 AM
I put that in the first part. Anyway, it is really stupid to use boolean and tables as well.
Man, that hurt… That was like saying it's stupid to use C++. You can't just go over and state that a bunch of people is stupid, just because they do things you don't.
I'm not saying that people are stupid, I was just saying that using boolean and tables is a bad idea, unless there is actually a good reason for doing it.
1522 posts
Location
The Netherlands
Posted 31 October 2013 - 07:08 AM
You should also explain what happens when you do the following:
local t = {
x = "random",
s = "key"
}
local x = t
A hint what you should explain is actually this "strange" behaviour:
x.lol = ":D/>"
print( t.lol )
If you dont understand whats going on there, why have you written this tutorial? 0.o
1688 posts
Location
'MURICA
Posted 02 November 2013 - 02:25 PM
What Engineer demonstrated has actually screwed me up quite a bit when I was developing with LÖVE a while ago, so it'd be good for OP to explain that.
4 posts
Posted 20 November 2013 - 10:53 AM
Nice tutorial thanks!
2 posts
Posted 12 December 2013 - 09:13 PM
since I havent found anything clear enough I want to ask it here now -> how do you exactly use it? I know how to set it up but do you activate it when a SAM is trying to lock you, or after he shoot its missile? And if you really can confuse the missiles with the ECM and you are very low to the ground could the ECM make it crash against the ground?
My English isnt the best but hopefully understandable
Thanks
10 posts
Location
The US of A
Posted 08 March 2014 - 01:57 AM
Thanks for sharing!
83 posts
Location
I 'm inside your brian
Posted 16 March 2014 - 02:22 AM
How do you execute a table?
7508 posts
Location
Australia
Posted 16 March 2014 - 02:40 AM
How do you execute a table?
I thought you knew Lua? You don't execute a table, in fact you don't 'execute' anything in programming; the term you're probably looking for is 'call' or 'invoke', but in either case you still do neither for a table. A table is a data structure similar to Associative Arrays in other languages, it is simply a place to store information.
Edited on 16 March 2014 - 01:40 AM
1281 posts
Posted 16 March 2014 - 10:14 AM
Well technically you could call a table if it has a __call metamethod, but that's probably not very relevant to whatever Issac is doing.
7508 posts
Location
Australia
Posted 16 March 2014 - 10:15 AM
[redacted]
Edited on 16 March 2014 - 09:16 AM
9 posts
Posted 16 March 2014 - 06:40 PM
While it might not have covered everything to do with tables, I still thought this was a very well written introductory tutorial to tables.
29 posts
Location
Well. I suppose between here and there.
Posted 19 March 2014 - 08:01 PM
How do you execute a table?
I thought you knew Lua? You don't execute a table, in fact you don't 'execute' anything in programming; the term you're probably looking for is 'call' or 'invoke', but in either case you still do neither for a table. A table is a data structure similar to Associative Arrays in other languages, it is simply a place to store information.
I thought you could do this, if you really wanted to:
MyTable = {
PrintStuff = function(Stuff)
print(Stuff)
end
}
MyTable.PrintStuff("Hello, World!")
That is technically calling a table. ;D
EDIT:
I think this is a great tutorial for beginners, OP. Good going.
Edited on 19 March 2014 - 07:02 PM
1281 posts
Posted 19 March 2014 - 08:06 PM
You're calling a function stored in a table, not the table itself. To call a table you'll need a __call metamethod.
7508 posts
Location
Australia
Posted 19 March 2014 - 10:49 PM
MyTable = {
PrintStuff = function(Stuff)
print(Stuff)
end
}
MyTable.PrintStuff("Hello, World!")
That is technically calling a table. ;D
technically that is accessing an entry in a table and then if the entry exists and is a function it invokes said function.
29 posts
Location
Well. I suppose between here and there.
Posted 19 March 2014 - 10:58 PM
MyTable = {
PrintStuff = function(Stuff)
print(Stuff)
end
}
MyTable.PrintStuff("Hello, World!")
That is technically calling a table. ;D
technically that is accessing an entry in a table and then if the entry exists and is a function it invokes said function.
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Edited on 19 March 2014 - 09:59 PM
7508 posts
Location
Australia
Posted 19 March 2014 - 11:03 PM
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows
tData(1) (normal brackets means invocation/calling) to work as though you typed
tData[1] (square brackets means access)
local tData = setmetatable({"hello", "world"}, {
__call = function(t, i)
return t[i]
end
})
As stated, it allows you do do the following
print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello
Edited on 19 March 2014 - 10:04 PM
29 posts
Location
Well. I suppose between here and there.
Posted 19 March 2014 - 11:19 PM
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows
tData(1) (normal brackets means invocation/calling) to work as though you typed
tData[1] (square brackets means access)
local tData = setmetatable({"hello", "world"}, {
__call = function(t, i)
return t[i]
end
})
As stated, it allows you do do the following
print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello
Ah, I haven't learned to use metatables effectively yet. I'm keeping busy learning other languages, too, like Java, C++ and Python, so I haven't really had the time. It may be worthwhile to do so, though. I shoot from place to place, lol.
1610 posts
Posted 21 March 2014 - 04:48 PM
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows
tData(1) (normal brackets means invocation/calling) to work as though you typed
tData[1] (square brackets means access)
local tData = setmetatable({"hello", "world"}, {
__call = function(t, i)
return t[i]
end
})
As stated, it allows you do do the following
print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello
Ah, I haven't learned to use metatables effectively yet. I'm keeping busy learning other languages, too, like Java, C++ and Python, so I haven't really had the time. It may be worthwhile to do so, though. I shoot from place to place, lol.
Meta tables are definitely some of the more powerful abilities of Lua. Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>
7508 posts
Location
Australia
Posted 22 March 2014 - 12:22 AM
Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>
Yeah kinda, the metamethods are considered to be a part of the table however, so by sheer technicality you are correct.
Edited on 21 March 2014 - 11:23 PM
1610 posts
Posted 23 March 2014 - 03:59 PM
Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>/>
Yeah kinda, the metamethods are considered to be a part of the table however, so by sheer technicality you are correct.
I guess it all depends on how technical you want to be :)/>
2 posts
Posted 29 March 2014 - 11:46 AM
When i use lua(), and run a function, it sometimes spits out "table: 2de4a71" (the numbers and letters are random) How do you get verbatim output out of it?
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows
tData(1) (normal brackets means invocation/calling) to work as though you typed
tData[1] (square brackets means access)
local tData = setmetatable({"hello", "world"}, {
__call = function(t, i)
return t[i]
end
})
As stated, it allows you do do the following
print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello
Ah, I haven't learned to use metatables effectively yet. I'm keeping busy learning other languages, too, like Java, C++ and Python, so I haven't really had the time. It may be worthwhile to do so, though. I shoot from place to place, lol.
Meta tables are definitely some of the more powerful abilities of Lua. Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>/>
I haven't ever heard of metatables before, that's cool!
7508 posts
Location
Australia
Posted 29 March 2014 - 11:25 PM
I haven't ever heard of metatables before, that's cool!
Yes metatables are very cool and can allow you to do some very powerful things; I do however suggest not using the code that I posted, while 'cool' it is very bad practise! I just made the code to prove a point :P/>
Edited on 29 March 2014 - 10:26 PM