Search code examples
moduleluarequireself

Storing a single function in a module


I am creating a prototype for an object and I would like the constructor to take a parameter that allows the object to get a function from an external module. Here is my code. I will further explain my problem below it.

Object prototype:

local obj = {}
local obj_mt = { __index = obj }

function obj.new( moduleString )
    local newObj = {}
    newObj:f = require( moduleString )

    return setmetatable( newObj, obj_mt )
end

return obj

Function module:

local function foo()
    -- code
end

return foo

When I run this, I get an error telling me that after newObj:function =, there should be function argument. Am I not returning a function through require( moduleString )? Another thing I need to mention is that if I use:

newObj.f = require( moduleString )

instead of:

newObj:f = require( moduleString )

there is no issue storing the function in the table newObj, but when I run it, the function cannot use the self parameter to reference newObj (or whatever variable name is used when the prototype is constructed). So basically what I need is a function stored in an external module which can access the parent table it is placed in when it is loaded using the self keyword.

EDIT: Here is the actual function which is standing in for foo():

local function AIfollow( path, L, R, T, B, X, Y )
    local L = L
    local R = R
    local T = T
    local B = B
    local x = self.img.x   <---- Here is the error
    local y = self.img.y
    local xLoc = ( X - X%tileSize )/tileSize
    local yLoc = ( Y - Y%tileSize )/tileSize

    if( xLoc < R and xLoc > L and yLoc < T and yLoc > B ) then
        local vx = self.img.x - x
        local vy = self.img.y - y
        local d = math.sqrt( vx*vx + vy*vy )
        self.img:setLinearVelocity( vx/d*self.speed, vy/d*self.speed )
    else
        self.img:setLinearVelocity( path[x][y].vX*self.speed, path[x][y].vY*self.speed )
    end
end

The details of this thing are not important; what I wanted to point out is that at the marked line I get an error telling me that it is attempting to index a global variable self which does not exist. What I do not know how to do is make the self in function AIfollow reference the table it is assigned to.


Solution

  • This is a different approach that's possibly closer to what you want.

    main.lua

    m = require 'module'
    
    a = m:new('foo','A',{'a','b','c'})
    a:f()
    
    b = m:new('foo','B',{'aa','bb','cc'})
    b:f()
    
    a:f()     --once again call A to verify two different objects exist
    

    foo.lua

    local function foo(self)
      print('Inside foo '..self.title)
      for k,v in pairs(self.dat) do
        print(k,v)
      end
    end
    
    return foo
    

    module.lua

    local m = {}
    
    function m:new(moduleString, title, table)
        self = {}
        self.title = title or ''            --none by default
        self.dat = table or {}              --optional table data
        self.f = require( moduleString )
        return self                         --return object reference
    end
    
    return m