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

Problem With My Code

Started by jay5476, 23 August 2013 - 02:51 AM
jay5476 #1
Posted 23 August 2013 - 04:51 AM
I am having problems with my program: lock:28: invalid key to 'next'.
it seems to be a problem with table.remove as i am seeing on the lua tutorial site i am using this correctly
and i even tried replacing k with 2
now I have link here: http://pastebin.com/gMs9NrRF
theoriginalbit #2
Posted 23 August 2013 - 05:08 AM
Ok the problem is with your loop.


for k, v in pairs(locked) do
  if v == file then
	table.remove(locked, k)
  end
end

The problem for this is due to how tables work…
A table can be thought of (in it's most basic form) as a Linked List, where each entry points to the next value (or node), this is how the pairs function works… By using the `next` function it returns the next node in the table, however you're removing the entry, so it is trying to call `next(nil)` which obviously causes a problem since `nil` doesn't have a next node.

So how do we fix this you say? we must create a new function, a function that will allow us to get the "next" value even though we are setting the current one to nil… this is how:


local function safePairs( _t )
  --# a table of keys
  local tKeys = {}
  --# populate the table of keys with the keys in the table we wish to iterate
  for k,v in pairs( _t ) do
	table.insert(tKeys, k)
  end
  --# create a variable for the index of the keys table
  local nAt = 0
  --# supply back to the iterative loop the function that returns the key and value from the supplied table
  return function()
	--# increment the index
	nAt = nAt + 1
	--# return the key and value for the original table
	return tKeys[nAt], _t[tKeys[nAt]]
  end
end
jay5476 #3
Posted 23 August 2013 - 05:26 AM
for my learning tell me if im correct please. does pairs() work in a way that it gets #table first and when It trys to get a key that doesn't exist ( because I removed it ) it calls upon an error, would I be able to do this: saving the key and then removing it after the iteration is done?
theoriginalbit #4
Posted 23 August 2013 - 05:42 AM
Not quite.

pairs works by getting the indexed values, then the key/value pairs. It will get the first value from the table, and from then on it will get the next value in the table by using the value it currently has, this means that when you nil that value it cannot get the next, causing the error. This cannot be solved by simply saving the index of the current one you're on, because there will be the same problem, it cannot use that key/index to be able to get the next value, the only way that you could get it to work is if you were to save the key for the next entry before nil'ing the current one, however this is essentially you writing your own iterative loop.

The code I suggested was the easiest way to do it if you're dealing with a key/value table, however if you're using just an indexed table (which I just noticed that I think you are) the easiest way to fix this problem is to do the following

for i = 1, #locked do
  if locked[i] == file then
	table.remove(locked, i)
  end
end
This will work as the loop increments the number, without worrying about the table…

Also as a slight side note, you should `break` the loop when you have removed the entry, unless you plan on having multiple entries that are the same value, in which case the above loop would have problems if the value you're removing is directly after one another, as the next one takes it's place, and then you miss it because you move on…….. this may be a little confusing, but I doubt that you're actually needing to do this, so use `break` after removing the value so the loop doesn't keep running because you've already found and removed the value.
Edited on 23 August 2013 - 06:56 AM
blipman17 #5
Posted 23 August 2013 - 08:29 AM
pairs/ipairs works by getting the indexed values, then the key/value pairs. It will get the first value from the table, and from then on it will get the next value in the table by using the value it currently has, this means that when you nil that value it cannot get the next, causing the error.

doesn't that only include pairs()? ipairs() does thesame with keys that are strings. and if i can remember it correctly ipairs() skips nil values to the next keys and therfore doesn't make an error in this code?

correct me if i'm wrong
theoriginalbit #6
Posted 23 August 2013 - 08:56 AM
doesn't that only include pairs()?
True, ipairs essentially does the same as the incremental for loop that I made… Didn't really think it through properly when I included ipairs in the reply… so an ipairs loop would not actually have the same error…

ipairs() does thesame with keys that are strings.
ipairs ignores key/value pairs, it only accesses indexed values… So given a table

local t = { ["foo"] = "bar", "hello", "world" }
for i,v in ipairs(t) do
  print(i," = ",v)
end
will print
1 = hello
2 = world
the key/value of `foo bar` would be ignored

and if i can remember it correctly ipairs() skips nil values
False. It will stop when a nil index is encountered. Given the following code

local t = { "hello", "world", [3] = "foo", [8] = "bar" }
for i,v in ipairs(t) do
  print(i," = ",v)
end
would output
1 = hello
2 = world
3 = foo