Is there a way to find out when you should call a function as a method?

What I am doing

What I am trying to do is make a program where it finds out if a function should be called with the : notation, or with the . notation.

I know the differences between the 2, but sadly I have yet to know if you can tell with code.

I also tried looking for examples in and outside the devforum.


An example code

local functions = {}; --// Container of my functions

function functions:fn1()
    print("fn1");
end

function functions:fn2()
    print("fn2");
end

function functions.fn3()
    print("fn3 called with \".\" notation");
end

--[[
    /*
    Default attempt, but this will print all function values
    I only want to print the ones defined with the ":" notation
    */
]]--

for k, v in pairs(functions) do
    if (rawequal(type(v), "function")) then
        print(k);
    end
end

I also tried playing around with the implicit self in methods but to no avail.

Note: I know how to call the functions as methods / with “.” notation as well.

So my question is this:

Is it possible, in Lua, to know when a function should be called as a method?

2 Likes

To answer your question, no. I don’t think there is a way to know which of the two a function is. You can call the function by doing

local t = {}

t.func = function()
    
end

function t:func()
    
end

t["func"]()

This would work with either type of function.

1 Like

Not exactly what I was looking for, I know that t:fn(...) is sugar for t.fn(t, ...) which itself is sugar for t["fn"](t, ...), but thank you anyways.

I will keep looking

You can’t tell from Lua code if a function has a self first argument (which the : defining does by default) unless you can string.dump the function and then read over its debug data, which is not possible within Roblox.

1 Like

could I do something like this and determine if it is defined with : ?

function functions:fn1()
    --// after everything else
    return rawequal(self, nil);
end

and then I can check the return of the function by calling it and determine if it’s a method?

The only issue I see is if I pass some args to the function and it gets picked up as self

I don’t get what you’re trying to do; self is a normal argument and if you’re adding a return rawequal don’t you already know how the function should be called to begin with?

A function defined using : is the same as this:

function object.functionWithoutColon(self, arg1, arg2, ...)

end

A function called using : is the same as this:

thing.functionWithColon(thing, arg1, arg2, ...)

This lets you do stuff like the following:

local Destroy = game.Destroy
Destroy(script) -- Same as script:Destroy() or script.Destroy(script)

The colon is simply a way to include self in your functions or supply the object before the colon as the first argument and it has no extra meaning or functionality behind the scenes.

So the simple answer to your question is no since all of these functions are simply just functions. The only option I can see is maybe using setfenv and setmetatable to add tags to the function (put custom meta into a metatable and use __index = getfenv(0) to maintain the default fenv) or just using a secondary table and using each function as an index.

1 Like

yeah now that I read it it doesn’t make sense. It was the first thing that came to mind so it wasn’t well thought out. I thank you for your input anyways.