liam
liam

Reputation: 33

attempt to call method 'func' (a nil value)

No matter how I approach Lua, I run into this error all the time, so I must not understand something inherit to the language:

attempt to call method 'func' (a nil value)

I've seen the error here a few times as well but the problem doesn't seem clear to me.

Here's my module:
actor.lua

Actor = {
    x = 0,
    mt = {},

    new = function()
        local new_actor = {}
        new_actor.x = Actor.x
        new_actor.mt = Actor.mt
        return new_actor
    end,

    test = function(self, a, b)
        print(a, b)
    end
}

I'm using Löve.
main.lua

require "game/actor"
local a = Actor:new() --works fine

function love.load()
    a.x = 10
    print(a.x) --output: 10
    a:test(11, 12) --error: attempt to call method 'test' (a nil value)
end

I'm also not sure when it's appropriate to use the previous styling over this in a module.

Actor = {
    x = 0
}
Actor.mt = {}

function Actor.new()
    print(42)
end

I'm honestly not sure what is more correct than the other but considering I run into a simple error either way, there's probably something I'm missing entirely?

Upvotes: 3

Views: 3696

Answers (1)

user5066707
user5066707

Reputation:

It looks like you're trying to instance a kind of class made of metatables. You basically need to assign new_actor's metatable with Actor.mt. (Resuming the problem: when you're indexing new_actor you're not indexing Actor in this case)

setmetatable(new_actor, Actor.mt);

Even if the metatable is being added, it won't work until you put the meta "__index" event to index a table containing your class methods/values, in this case:

Actor.mt = {
    __index = Actor
};

I'd suggest moving your class methods/values into a new table, like Actor.prototype, Actor.fn, etc... avoiding conflicts:

Actor.fn = {
    test = function(self, a, b)
        print(a, b)
    end
};

Actor.mt = {
    __index = Actor.fn
};

More about metatables in Lua 5.3 manual.

Upvotes: 1

Related Questions