Error in method

My program includes classes for Person, Queue, and Elevator objects. The Elevator class includes a method for moving an elevator up or down:

function Elevator:move()
    if self.y > self.targety then
        self.y = self.y - 1
        if elevatorQ:numberIn() >= 1 then
            for i = 1, elevatorQ:numberIn() do
                elevatorQ[i] [1]:moveDown()
            end
        end
    end
    if self.y < self.targety then
        self.y = self.y + 1
        if elevatorQ:numberIn() >= 1 then
            for i = 1, elevatorQ:numberIn() do
                elevatorQ[i] [1]:moveUp()                 <--------- crashes here
            end
        end
    end
end

Person objects have moveUp and moveDown methods, and I have a global Queue object called elevatorQ that contains references to Person objects that must move with the Elevator. When the code above runs, it crashes with the message “Attempt to index nil value” where I have indicated. elevator[i] [1] is the field that contains a reference to a Person. Can someone please tell me what I’m doing wrong here?

Sorry about the lack of indentation. When I pasted the code, the indentation was there; when it posted, it was gone!

@Eustace I’ve fixed it, you need to add ~~~ before and after the code to render it as code (you can edit your post to see what I added).

Thanks, Simeon.

Either i or 1 is out of ranger of the elevator array. What does the numberIn method do? You can get the length of an array with # , eg #elevatorQ to get the length of the array’s first dimension and then #elevatorQ[i] to get the length of nested arrays. You can also check whether a nested array exists before trying to subscript it, eg if elevatorQ[i] then . If you add in these checks, your code will be safer. Though you should also try to find why you’re trying to access it with an out of range index. Remember that each nested array must also be initialised before it can be accessed using elevatorQ[i] = { }

Off-topic, anyone else had issues with back tick code notation sometimes not working in the forum?

let’s try again: Either i or 1 is out of ranger of the elevator array. What does the numberIn method do? You can get the length of an array with # , eg #elevatorQ to get the length of the array’s first dimension and then #elevatorQ[i] to get the length of nested arrays. You can also check whether a nested array exists before trying to subscript it, eg if elevatorQ[i] then . If you add in these checks, your code will be safer. Though you should also try to find why you’re trying to access it with an out of range index. Remember that each nested array must also be initialised before it can be accessed using elevatorQ[i] = { }

^ weird, copied and pasted the same comment, and the back-tick notation works the second time, but not the first.

@yojimbo2000 What is back tick code notation. I would try it, but I’m not sure what it is.

The numberIn method is needed because of the structure of the Queue objects. Each one is a table of tables. The first table contains an index key, and a table value. The tables then contain two index keys, first value to a reference to a Person object, the second to an integer value used elsewhere. When the Queue is constructed, the places where Person references will go is filled with zeros. The numberIn method goes through the Queue, counting Persons, until it finds a zero value.
Using the # would not give me the information I need. I already know the array length, I set that when I construct the Queue.

I’m not sure what you mean by “out of ranger of the elevator array”. The elevatorQ has twelve places where references to Persons can be stored. When I run the method above, I have two Persons in the Queue. The numberIn method returns 2 (I tested that). So the innermost for/do loop should run twice, once for elevatorQ[1] [1], then again for elevatorQ[2] [1]. But it won’t run even once. It won’t run, even if I replace the i with a 1.

@Eustace The easiest way to figure out what’s going on is to put a print statement just before the line causing the problem. Print out different values until you figure out what the cause is. It’s hard to find a problem in someone else’s code without having the code to run.

That’s how I found out that numberIn was working right. I added print(elevatorQ:numberIn()) right before the inner for/do loop.
My problem right now is that I’m still really unfamiliar with Lua, so the possible things that could be wrong is a really long list, and the error messages don’t mean much to me. Attempt to index nil value, for example. Is index being used as a verb in that sentence? It sounds like it. Does that mean that indexing is what happens when a value is replaced by another value in a table? Or is indexing what happens when a value is looked for (and in this case, perhaps, a nil is found)?

Is the thing I’m trying to do in this line allowed? I’m trying to call a Person method. As if the code read “aPersonObject:moveUp()”. But instead of using a variable name to specify the Person object, I’m using the array location where the reference is stored, “elevatorQ[1] [1]:moveUp()”. Is this allowed in Lua?

In your above code, you say elevatorQ[i] [1]:moveUp() causes the problem. You also said that the variable i had a valid value. Since you get a nil error message, then that means elevatorQ[i] [1]:moveUp() isn’t pointing to anything. You need to check on how you’re creating an instance of whatever it’s supposed to be pointing to. Like I said above, it’s hard to debug someone else’s code without having it to run.

If I understand you correctly, you are saying that at the time the code runs, elevatorQ[i] [1] does not contain a reference to a Person object, so the Person class method moveUp() points to nil? What does that have to do with indexing?!? This error message is really confusing and frustrating to me.

Your elevatorQ[i][1]:moveUp() is being indexed by [i][1]. You have to look at elevatorQ and see how you’re creating an instance using it. I’ll try to give you an example later.

@Eustace Here’s a simple example. I’m not sure if this will even help since I don’t know what your classes look like.

Code removed. Not needed anymore.

I hope I’m not sounding too irritated here; I really appreciate that you are trying to help.
I was so happy and proud just yesterday - I thought I had gotten all the bugs out of this Queue class! I have working addTo() and removeFrom() methods. At least they appeared to be working. Sigh.
I am certainly creating instances of Persons and Queues. I know for sure about Persons, because each one has a visible, drawn appearance on the screen. I know for sure about Queues, because each one contains an x coordinate that the Person assigned to it uses as a target to move toward; and there they are, visibly marching toward their target once added to a Queue.
I have some buttons on the screen to generate events when pressed. The Add Person button creates an instance of a Person, and adds it to the floor1Q Queue. The person appears, and moves across the screen to it’s assigned position. I hit the button a few more times; soon I have a line of Persons waiting at the elevator door.
The second button “moves” the person at the head of the floor1Q into elevatorQ. The function executed by this button looks like this:

function test()
    elevatorQ:addTo(floor1Q:releaseFrom(1))
    print("test")
end

When I hit the button, the person moves to the screen position assigned to elevatorQ[1]. Hit the button again, another person joins the first, offset by 10 pixels (each Queue position is 10 pixels off from the previous position, the x coordinate is stored in exampleQ[i] [2]).

Did I mention that the Queue objects are globals? They are created in the setup() function.

When I hit the third button, trouble. The function executed by this button looks like this:

function test2()
    elevator1:moveTo(205)
    print("test2")
end

The moveTo() method gives the elevator object a new target y coordinate. So far, so good. Now each time the draw() function runs, the elevator’s y coordinate ticks one step closer to it’s new target y. At least, that’s what happens if I comment out the line that’s crashing in the Elevator:move() method, the method I am having problems with, the method whose code I included in my original question.

So much is working! But I can’t get my Elevator to move it’s passengers. Not much of an elevator, is it?

could you post all of your code?

I’m not sure how best to do that. There’s a lot of code here. Maybe if I do it one tab at a time?
Here is the main tab:

-- Elevator2

-- Use this function to perform your initial setup
function setup()   
    -- setup touch buttons
    addPersonButton = Button("Add Person")
    addPersonButton.pos = vec2(100, HEIGHT - 70)
    addPersonButton.action = function () addPerson() end
    otherButton = Button("Test")
    otherButton.pos = vec2(300, HEIGHT - 70)
    otherButton.action = function () test() end
    anotherButton = Button("Test 2")
    anotherButton.pos = vec2(400, HEIGHT - 70)
    anotherButton.action = function () test2() end
    
    -- setup globals
    persons = {}
    setCallButtons()
    elevator1 = Elevator(510, 25)
    floor1Q = Queue(100, 445)
    floor2Q = Queue(100, 445)
    floor3Q = Queue(100, 445)
    floor4Q = Queue(100, 445)
    elevatorQ = Queue(12, 660)
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
    
    -- draw functions
    drawBuilding()
    drawCallButtons()
    addPersonButton:draw()
    otherButton:draw()
    anotherButton:draw()
    elevator1:draw()
    drawPeople()
    
    -- move functions
    elevator1:move()
    movePeople()
end

function touched(touch)   
    if touch.state == ENDED then
        addPersonButton:touched(touch)
        otherButton:touched(touch)
        anotherButton:touched(touch)
    end
end