This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
cheekycharlie101's profile picture

a couple of things i do not understand at all.

Started by cheekycharlie101, 01 December 2012 - 04:53 AM
cheekycharlie101 #1
Posted 01 December 2012 - 05:53 AM
ok, so there are 2 things in CC that i just cannot get my head round. the first one is tables. like how do you use tables.
i know they are defined like so:


local words = { "word1", "word2" }
but i dont get how to use them. the next thing is in pairs. i see this in code all the time but what does it do?


for k,v in pairs do
what does that mean?. as im sure there are several different ways of using this, im going to state which one i need.

im making a rednet login server. he is what i need
you send the user name to the login server. it then checks to make sure the id is approved. if the id and the user exists it sends the password back.

so here is a little code:


users = { "user1", "user2" } usernames
ids = { 1, 2, 3 } -- approved id's
pass = { "pass1", "pass2" }
senderId, message,  distance = rednet.receive()
ok so if the message matches user1 it sends pass1. if it matches user2 it sends pass2. it only sends them though if the id of the sender is in the ids table.
feel free to add any more uses.
thanks -Cheeky
Sammich Lord #2
Posted 01 December 2012 - 06:03 AM
For tables:
You index tables like this:

local tableName = {
  ["Hello"] = 10,
  [1] = 90
}
So if I do:

print(tostring(tableName["Hello"]))
print(tostring(tableName[1]))
I would get this output:

10
90
Tables can also have just plain vars, tables inside tables and functions inside.
For example:

local tableName = {}
tableName.var = "Hello"
tableName.func = function(str)
  print(str)
end
That is the basic. More help can be found on Google.
As for pairs/ipairs, pairs goes through every index of a table, ipairs only goes through the indexes that are numbers.
For example:

local tableName = {
  [1] = "Hello",
  ["Hello World"] = 1,
  [2] = "World"
}
local str
for k,v in ipairs(tableName) do --k is the index and v is the value
  str = str..v
end
print(str)
That would output:

HelloWorld
However pairs would index all of the indexes no matter if there are a string or a number.
For example:

local tableName = {
  ["Hello"] = "Hello",
  [" "] = " ",
  ["World"] = "world"
}
local str
for k,v in pairs(tableName) do
  str = str..v
end
print(str)
That would output:

Hello world
I hope this helped! If you need any more help ask my good friend, Google.
If this helped a +1 would be nice.
billysback #3
Posted 01 December 2012 - 06:09 AM

for k,v in ipairs(tableName) do --k is the index and v is the value
  str = str..v
end

I wouldn't use this code ever any more; use:

for i=1,#tableName do
  str = str..tableName[i]
end
this iterates the fastest out of all iteration methods in Lua, the only reason you should ever not use it is when table's have non-numerical keys, in which case you should use pairs.

You should probably explaine key/values as well, you just used them:
in a basic table you would define it as:

local table = {value, value, value}
which is effectively a simplistic way of writing:

local table = {
  [1] = value,
  [2] = value,
  [3] = value
}
the [1] is the key, so to get value 2 you would use:

table[1]

however, you can set things like:

local table = {
  x = 10,
  y = 10,
  text = "Hello world",
}
to access these variables you can either use:

local x = table.x
or

local x = table["x"]
cheekycharlie101 #4
Posted 01 December 2012 - 06:16 AM

for k,v in ipairs(tableName) do --k is the index and v is the value
  str = str..v
end

I wouldn't use this code ever any more; use:

for i=1,#tableName do
  str = str..tableName[i]
end
this iterates the fastest out of all iteration methods in Lua, the only reason you should ever not use it is when table's have non-numerical keys, in which case you should use pairs.

You should probably explaine key/values as well, you just used them:
in a basic table you would define it as:

local table = {value, value, value}
which is effectively a simplistic way of writing:

local table = {
  [1] = value,
  [2] = value,
  [3] = value
}
the [1] is the key, so to get value 2 you would use:

table[1]

however, you can set things like:

local table = {
  x = 10,
  y = 10,
  text = "Hello world",
}
to access these variables you can either use:

local x = table.x
or

local x = table["x"]
so how could i use this to code my rednet login server? this is really hard :(/>
Cranium #5
Posted 01 December 2012 - 06:18 AM
Down and dirty turtorial for pairs/ipairs:
 local indexTable = { "Index 1", "Index 2" }
local nameTable = { indexOne = "One", indexTwo = "Two" }
for i, v in ipairs( indexTable ) do
--this will iterate(repeat) over a table that contains numerical(numbered) indexes(slots)
--In this instance we are using indexTable
- -by default, tables with no index designation will become numerically indexed.
print( i .. " " .. v)
end
-- Result:
-- "1 Index 1"
-- "2 Index 2"
-- You can see that it will print the index ( i ), then the value ( v )
-- now for pairs
for i, v in pairs( nameTable ) do
--This will iterate over non-indexed (non-numbered) objects in the table
-- in this instance we will be using nameTable
-- as you can see, we now define each index with a variable.
-- ipairs would not work for this table, as there are no numerical indices.
print( v ) end -- Result: -- "One" -- "Two"
I hope I helped, but you would get a better explanation on the Lua-users wiki website.
Sammich Lord #6
Posted 01 December 2012 - 06:19 AM
I never see speed a issue in Lua. I also believe using pairs makes your code look a lot nicer. Using pairs also allows me to do something like this:

os.pullEvent = os.pullEventRaw
local users = (
  ["user1"] = "password1",
  ["user2"] = "password2"
)
local access = false
while not access do
  term.clear()
  term.setCursorPos(1,1)
  write("User: ")
  local userInput = read()
  write("Pass: ")
  local passInput = read("*")
  for k,v in pairs(users) do
	if userInput == users[k] and passInput == users[v] then
	  access = true
	else
	  print("Bad login!")
	  sleep(2)
	end
  end
end
print("Logged in!")
I hope this helps with your rednet login server!
Cranium #7
Posted 01 December 2012 - 06:23 AM
For tables:
You index tables like this:

local tableName = {
  ["Hello"] = 10,
  [1] = 90
}
So if I do:

print(tostring(tableName["Hello"]))
print(tostring(tableName[1]))
I would get this output:

10
90
Tables can also have just plain vars, tables inside tables and functions inside.
For example:

local tableName = {}
tableName.var = "Hello"
tableName.func = function(str)
  print(str)
end
That is the basic. More help can be found on Google.
As for pairs/ipairs, pairs goes through every index of a table, ipairs only goes through the indexes that are numbers.
For example:

local tableName = {
  [1] = "Hello",
  ["Hello World"] = 1,
  [2] = "World"
}
local str
for k,v in ipairs(tableName) do --k is the index and v is the value
  str = str..v
end
print(str)
That would output:

HelloWorld
However pairs would index all of the indexes no matter if there are a string or a number.
For example:

local tableName = {
  ["Hello"] = "Hello",
  [" "] = " ",
  ["World"] = "world"
}
local str
for k,v in pairs(tableName) do
  str = str..v
end
print(str)
That would output:

Hello world
I hope this helped! If you need any more help ask my good friend, Google.
If this helped a +1 would be nice.
WOW, MUUUUUCH better explanation than mine.
billysback #8
Posted 01 December 2012 - 06:24 AM
  
for k,v in pairs(users) do
		if userInput == users[k] and passInput == users[v] then
		  access = true
		else
		  print("Bad login!")
		  sleep(2)
		end
  end

If you had read what I had said I went on to say:
the only reason you should ever not use it is when table's have non-numerical keys, in which case you should use pairs.

Also, this code wouldn't work? You are looking for the key "v" in table "users" which you are looping through, that check is just wrong :P/>
I think this is what you meant:

for k,v in pairs(users) do
		if userInput == k and passInput == v then
		  access = true
		else
		  print("Bad login!")
		  sleep(2)
		end
  end
and a better way to do this in any case would be:

if users[userInput] == passInput then
  access = true
else
  print("Bad login!")
  sleep(2)
end

Just to show you why what you did is wrong, let's say the userInput is "Billy" and the passInput is "Cake"
then let's say the table is:

local users = {
   ["Billy"] = "Cake"
   ["Cake"] = "Cookie"
}

then the loop would check:

"Billy" == users[key]
so
"Billy" == "Cake"
and

"Cake" == users[value]
so
"Cake" == "Cookie"

and there was some discussion about speeds of iteration, if you do your research you will find that what I said is true :P/>
Sammich Lord #9
Posted 01 December 2012 - 06:28 AM
Spoiler
  
for k,v in pairs(users) do
		if userInput == users[k] and passInput == users[v] then
		  access = true
		else
		  print("Bad login!")
		  sleep(2)
		end
  end

If you had read what I had said I went on to say:
the only reason you should ever not use it is when table's have non-numerical keys, in which case you should use pairs.

Also, this code wouldn't work? You are looking for the key "v" in table "users" which you are looping through, that check is just wrong :P/>
I think this is what you meant:

for k,v in pairs(users) do
		if userInput == k and passInput == v then
		  access = true
		else
		  print("Bad login!")
		  sleep(2)
		end
  end
and a better way to do this in any case would be:

if users[userInput] == passInput then
  access = true
else
  print("Bad login!")
  sleep(2)
end
Yeah, I've been up for a while. Thanks for correcting me!
Cranium #10
Posted 01 December 2012 - 06:39 AM
You can shorten your tables in another way:


local userTab = {
[1] = {user = "cheekycharlie", pass = "Password"}
[2] = {user = "cranium", pass = "Password"}
}
--this table contains IDs, usernames, and passwords.

for i, v in ipairs(userTab) do -- start user/pass check loop
  if userTab[i].user == "cheekycharlie" and userTab[i].pass == "Password" then
    print("Success")
    break --ends the checking loop so you don't get both success and failure message.
  else
    print("Failed")
  end
end

This is how I usually check usernames and passwords. Using one table is much easier in my opinion.
billysback #11
Posted 01 December 2012 - 06:43 AM
Once again; Don't use ipairs it's effectively depreciated (using i=1,#table = better)
Sammich Lord #12
Posted 01 December 2012 - 06:45 AM
Once again; Don't use ipairs it's effectively depreciated (using i=1,#table = better)
Tell me how using that loop is DRASTICALLY better then using pairs or ipairs?
billysback #13
Posted 01 December 2012 - 06:47 AM
It's better than pairs because it iterated in numerical order; pairs doesn't.
Pairs is only better when iterating through a table with non-numerical keys.

Then this is why it is faster:
For the discussion between ipairs being slower than pairs;
http://facepunch.com...ad.php?t=875909

this experiment shows the comparisons of speed between the two at different sizes of tables; It seems to portray that for smaller tables ipairs is faster however for much larger tables pairs begins to become more efficient.

Also, if you look down the thread there is a new graph which suggests that a for statement is the fastest way to parse a table.
Spoiler
(quote from me)
Cranium #14
Posted 01 December 2012 - 06:49 AM
Once again; Don't use ipairs it's effectively depreciated (using i=1,#table = better)
I should have used pairs INSTEAD of ipairs(just in case), but using for i = 1,#userTab is no better than using pairs/ipairs.

Edit: The only time I would use for i = 1, #table is when I am using a funciton where the length of the table would change on a regular basis.
Edited on 01 December 2012 - 05:50 AM
billysback #15
Posted 01 December 2012 - 06:50 AM
I should have used pairs INSTEAD of ipairs(just in case), but using for i = 1,#userTab is no better than using pairs/ipairs.

evidence suggests otherwise…
For the discussion between ipairs being slower than pairs;
http://facepunch.com...ad.php?t=875909

this experiment shows the comparisons of speed between the two at different sizes of tables; It seems to portray that for smaller tables ipairs is faster however for much larger tables pairs begins to become more efficient.

Also, if you look down the thread there is a new graph which suggests that a for statement is the fastest way to parse a table.
Spoiler

Obviously the difference is so miniscule that it doesn't matter, but it still convinced me to stop using ipairs.
Sammich Lord #16
Posted 01 December 2012 - 06:52 AM
Once again; Don't use ipairs it's effectively depreciated (using i=1,#table = better)
I should have used pairs INSTEAD of ipairs(just in case), but using for i = 1,#userTab is no better than using pairs/ipairs.

Edit: The only time I would use for i = 1, #table is when I am using a funciton where the length of the table would change on a regular basis.
His graph does show that for is faster for indexing larger tables. But, nothing very drastic for small tables.
Cranium #17
Posted 01 December 2012 - 06:53 AM
Meaning ipairs was faster than pairs by 0.0000000341seconds.
If that amount of time is really important to you, then by all means… All I said is that iterating over the NUMBER OF INDICES is not what I wanted to do. Iterating over #table is something that is not very flexible, and is hard to get the results you really want.
billysback #18
Posted 01 December 2012 - 06:56 AM
You get the exact same results as ipairs?

for k,v in ipairs(table) do
   <code>
end

for i=1,#table do
   local v = table[i]
   <code>
end
adding the variable "v" was for the sake of the example, it is obviously not a necessity.
also, a huge advantage of this is that you can skip values, by doing i = i + 1 you will skip the following value.
This can be extremely useful when pairing each index with the one after it (which I have done before)

I found that graph and decided that what was the point in using an inferior method when I could be using something which adds no more complexity and is faster, even marginally.
Lyqyd #19
Posted 01 December 2012 - 06:57 AM
I would say that using ipairs() isn't necessarily a bad thing. It has its place, and I would say makes code a bit easier to read in certain situations. With the small size that typical tables reach in ComputerCraft, the performance it for using ipairs() is pretty trivial, so there's no need to harp against it.

That said, it is valuable to know that manual iteration is somewhat faster (which is to be expected), as it could be a useful optimization for very large tables.
ChunLing #20
Posted 02 December 2012 - 02:06 AM
I've never found ipairs easier to read, I only ever started using it because I assumed it must be faster somehow, since it did the same basic thing.

On the other hand, pairs is very useful and more robust than the other options, and I generally prefer it.