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

Attempt To Index ? (a Number Value)

Started by br456, 17 November 2013 - 09:51 AM
br456 #1
Posted 17 November 2013 - 10:51 AM
I made a program to get items from my chest. There is one chest per item. I have a base computer broadcasting the message "dirt", but it sends this error every time: testr:7:attempt to index ? (a number value) Here is the code:

rednet.open("left")
function split(str, pat)
  local t = {}
  local fpat = "(.-)" .. pat
  local last_end = 1
  local s, e, cap = str:find(fpat, 1)
  while s do
	if s ~= 1 or cap ~= "" then
  table.insert(t,cap)
	end
	last_end = e+1
	s, e, cap = str:find(fpat, last_end)
  end
  if last_end <= #str then
	 cap = str:sub(last_end)
	 table.insert(t, cap)
  end
  return t
end
while true do
  m = { }
  x,y,z=rednet.receive()
  m = split(x, ",")
  if m[1] == "dirt" then
	a = tonumber(m[2])
	b = a * 5
	rs.setOutput("right", true)
	sleep(B)/>/>/>
	rs.setOutput("right", false)
  end
end

I have made a simple program to receive a rednet signal and send a redstone signal. I split the string to find the amount of item needed, but it gives me an error: testr:5: attempt to index ? (a number value). Here is the code:

rednet.open("top")
local function split(str, pat)
  local parts = {}
  for part in str.gmatch( "[^" .. pat .. "]+" ) do
    table.insert( parts, part )
  end
  return part
end
while true do
  m = {}
  x,y,z = rednet.receive()
  m = split(x, ":")
  if m[1] == "cobble" then
    a = tonumber(m[2])
    b = a * 5
    rs.setOutput("left", true)
    sleep(B)/>/>
    rs.setOutput("left", true)
  end
end
Edited on 17 November 2013 - 08:01 PM
Engineer #2
Posted 17 November 2013 - 02:12 PM
Im not sure where the issue is, since you havent posted the full error. Those contain a line number, which you didnt give.
But, there is something more simple to split:

local function split( str, pat )
    local parts = {}
    for part in str:gmatch( "[^" .. pat .. "]+" ) do
       table.insert( parts, part )
    end
    return part
end
br456 #3
Posted 17 November 2013 - 03:27 PM
The error occurs on line 7. Thanks for the function

Engineer, your function is also returning with an error: testr:5: attempt to index ? (a number value)
theoriginalbit #4
Posted 17 November 2013 - 07:41 PM
Ok so what the error means….


What is "attempt to index"?

In programming languages we have variables/structures that can store large amounts of data for us in an organised manner, in most languages these are called Arrays, in Lua these are called Tables. In order to access this data we must index the table to retrieve its contents. This can be done in a few ways in Lua.
First lets assume we have this table

local someTable = {
  "hello",
  "world",
  ["foo"] = "bar",
  ["key"] = "value",
  func = function(self) print("hi from "..tostring(self)) end
}
in the above table we have 5 values, the first two are stored under the indexes 1 and 2, the last three are stored under the index/key "foo", "key", and "func".
now the different methods of getting these variables are as follows


someTable[1]
this will get the first value "hello", placing 2 in the square brackets will get "world"


someTable["foo"]
this will get "bar" from the table, if "foo" were replaced with "key" or "func" the second or third would be returned respectively


someTable.foo
this will also return "bar", same can be done with "key" or "func"

This however will not work

someTable[foo]
as it assumes foo is a variable, which is currently nil, and there is nothing in the table with the index/key nil.

Now accessing the function, the 5th entry, is the same as above, however there is another way as well.
the standard way

someTable.func
--# or
someTable["func"]

other way

someTable:func

now why would we do it this way?

As you can see in the function we have a variable named "self" this is because we want to do something with the table the function is stored in, so if we wanted to do it the normal way we would need to do this

someTable.func(someTable)
which as you can see is quite verbose, this is why the creators of Lua have given us this syntactical sugar

someTable:func()
which gives the reference for the table as the first argument.

Now by this point you may be wondering why I'm telling you all this… and the reason is because the error you're getting is happening on the line where you do the following

str:find --# your code
str:gmatch --# Engineers code
now from what you just learnt you can see that we're attempting to call a function on the string variable in order to find parts of it, and of course the function wants a reference to the string so that it can perform the actions. Now lets expand on this with the rest of the error message


? (a number value)

this part of the message tells you why the indexing has failed, now remember from the above section how I stated that you can only index a table, well strings are tables. However other data types such as numbers, booleans, nil, etc are not. This means that when we attempt to do the following

local num = 5
num:find()
--# or
num.find()
Lua will throw us the error attempt to index ? (a number value)

similarly with booleans

local bool = true
bool:find()
--# or
bool.find()
will result in attempt to index ? (a boolean variable)

ignoring the fact of course that both numbers and booleans don't have any function called "find" it was just a simple example to illustrate a point.


What does this all mean for me?

well it means that somewhere when you're calling your split function, you're providing it with a number, not a string like it wants. This is because of how rednet.receive works

local sendersComputerId, messageSent, distanceMessageWasSent = rednet.receive()
is how the values are returned, meaning that you're attempting to perform a split on the ID of the computer that sent you the message, not the message itself.

Note: also use Engineers function, its a much more efficient function to use ;)/>
Lyqyd #5
Posted 17 November 2013 - 09:02 PM
I merged the other topic you created into this one. I'm not sure why you needed a second topic. Both of your original posts are now combined into the first post of this topic.