"Attempt to index local..." Why am I getting this error?

26,688

Solution 1

If you want to be able to do testSlide.slideToImage() you have to modify newCarousel so that it returns a table with a function inside it. The simplest implementation is the following:

function newCarousel(images)
    local t = {}
    t.slideToImage = function() 
        print("ah!")
    end
    return t
end

You can even build t and return it on a single step; the following code is equivalent to the one above:

function newCarousel(images)
    return {
        slideToImage = function() 
            print("ah!")
        end
    }
end

Solution 2

Because newCarousel returns nothing, so testSlide is nil, so when you try to index it (testSlide.slideToImage is exactly equivalent to testSlide["slideToImage"]) you get an error.

I would recommend reading Programming in Lua. You may be able to work out the language's syntax, semantics, and idioms by trial and error, but it'll take you a lot longer.

Solution 3

The code you've got now, as Mud stated, doesn't return anything. (This is not Scheme or Ruby or the like where the last expression is the return value.) Further, you seem to be thinking that newCarousel is an object. It isn't. It's a function. When you've finished calling newCarousel it's over. It's done its work, whatever that may be (which in your case is creating a local variable that is promptly dropped and returning nil).

Correct code for this would look more like:

function newCarousel(images) 
    return function() 
        print("ah!")
    end
end

local testSlide = newCarousel(myImages)
testSlide()

Here I now have newCarousel creating an (anonymous) function and immediately returning it. This anonymous function is bound to testSlide so I can invoke it any time I like for as long as testSlide remains in scope.


It's instructive to look at the generated code when playing with Lua. First let's look at what luac churns out for your code:

main <junk.lua:0,0> (8 instructions, 32 bytes at 0xeb6540)
0+ params, 2 slots, 0 upvalues, 1 local, 3 constants, 1 function
    1   [5] CLOSURE     0 0 ; 0xeb6720
    2   [1] SETGLOBAL   0 -1    ; newCarousel
    3   [7] GETGLOBAL   0 -1    ; newCarousel
    4   [7] GETGLOBAL   1 -2    ; myImages
    5   [7] CALL        0 2 2
    6   [8] GETTABLE    1 0 -3  ; "slideToImage"
    7   [8] CALL        1 1 1
    8   [8] RETURN      0 1

function <junk.lua:1,5> (2 instructions, 8 bytes at 0xeb6720)
1 param, 2 slots, 0 upvalues, 2 locals, 0 constants, 1 function
    1   [4] CLOSURE     1 0 ; 0xeb6980
    2   [5] RETURN      0 1

function <junk.lua:2,4> (4 instructions, 16 bytes at 0xeb6980)
0 params, 2 slots, 0 upvalues, 0 locals, 2 constants, 0 functions
    1   [3] GETGLOBAL   0 -1    ; print
    2   [3] LOADK       1 -2    ; "ah!"
    3   [3] CALL        0 2 1
    4   [4] RETURN      0 1

In your code the mainline creates a closure, binds it to the name newCarousel, gets that value, gets the value of myImages and does a call. This corresponds to local testSlide = newCarousel(myImages). Next it gets the slideToImage value from the local table (testSlide). The problem here is that testSlide isn't a table, it's nil. This is where your error message is coming from. This isn't the only error, mind you, but it's the first one the runtime sees and is what's making everything choke. If you'd returned an actual function from newCarousel you'd get a different error. If, for example, I'd added the line return slideToImage to the newCarousel function, the error message would have been "attempt to index local 'testSlide' (a function value)".

Share:
26,688
Elliot Bonneville
Author by

Elliot Bonneville

Full-stack developer with a focus on building single-page web apps with TypeScript, React and Node.js. Also passionate about design systems and helping SaaS startups improve their revenue through digital marketing. Currently looking for new contracts for Q1 and Q2 2020.

Updated on July 09, 2022

Comments

  • Elliot Bonneville
    Elliot Bonneville almost 2 years

    I'm new to Lua and trying to get things sorted in my head. I tried this code:

    function newCarousel(images) 
        local slideToImage = function() 
            print("ah!")
        end
    end
    
    
    local testSlide = newCarousel(myImages)
    testSlide.slideToImage()
    

    Which gave me this error:

    Attempt to index local "testSlide" (a nil value)...

    Why is this?