Calling function multiple times or call it once with tables as parameter

So…

Which one should I do? Calling the same function multiple times with multiple arguments, or call it once by using 1 parameter which will be a table? Here’s what I mean:

local function doSomething(arg1, arg2, arg3, arg4)
    -- Do something with the parameters
end
local function doSomething(tab: {})
    for i, v in pairs(tab) do
        -- Do something with index and value
    end
end

Not sure which one I should use, so yeah.

This isn’t really an answer to your question, but you can type check for tables with {}? I had no idea.

Yeah, you can :smile: somerandomalphabetinspoiler

And to answer your question, it really depends on how many arguments you want to pass. If you only really need a few, you can use single variables, but if you are using dozens of arguments, you are going to want to use a table. You could do something like:

local argTable = {
   ["arg1"] = 7,
   ["arg2"] = 2,
   ["arg3"] = "WOW"
}

local function doSomething(argTable)
    for index, value in pairs(argTable) do
        print(tostring(index..value))
    end
    -- or
    print(argTable["arg1"]) -- If you only want one specific argument
end

Then again, I’d say it’s up to personal preference. If you are only planning to have four arguments. I’d personally do your first example.

1 Like

Honestly i wouldn’t use a table to pass thousands of arguments as it wouldn’t make sense just passing that many arguments. It just depends on the job of the function, and what it does. Such as a function to set the properties of an object can be function Set(object: Instance, properties: { string: any })

1 Like

To be honest, yeah. I think that’s good. But let me give an example of why I actually created this post. Let’s say I give the name, description, original position of a frame (UDim2) and some other stuff so that it can create a menu button and bind the frame. Would it make sense for me to pass a table as argument so that it loops through the table to create all the buttons at once?

Could you provide the hypothetical code you are talking about? It doesn’t need to be a bunch of code, just the gist of what you mean.

Don’t forget variadic functions exist!

local function myFunction<T>(...: T): ()
    local args = table.pack(...)

    for i = 1, args.n do print(args[i]) end
end

myFunction("One", "Two", "Three", "Four")

doSomething(“hello”, “nice”, “to”, “meet”)
doSomething(“something”, “else”, “here”, “yay”)

OR

local function doSomething(argTable)
– Do something with the parameters
end

doSomething({“hello”, “nice”, “to”, “meet”})
doSomething({“something”, “else”, “here”, “yay”})

I’m more curious about the performance now.

The difference is that, in the first case, you’re passing four arguments to a function, while in the second case, you’re passing one argument, a table.
The first method is more compact and readable. The second method has the advantage that you can pass a table, which means you can pass it to a function that takes a table as a parameter.
To answer your question about performance, it doesn’t matter which one you use, because the Lua virtual machine will do the same thing in either case: it will create four slots in the virtual stack and put the four values in those slots.

shoot i need to get better at typechecking :skull:

doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)
doSomething(arg1, arg2, arg3, arg4)

or

local function doSomething(tbl)
– Do something with the parameter
end

doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})
doSomething({arg1, arg2, arg3, arg4})

If both of them are optimized the same way, then I guess it’s a matter of taste. But I think the 2nd way is a bit easier to read.

There’s no difference in the way Lua will handle it.
When the function is called, the arguments are put on the stack, the function is compiled and the local variables are instantiated and initialized.
This means that the function is called only once, no matter how many arguments you pass.
The only difference is that in the second case, you have to unpack the table and put the arguments in local variables.

What do you mean? Do you just mean writing types? It comes natural since I’m used to working with typed languages. :stuck_out_tongue:

I’d probably recommend forcing yourself to use strict mode if you want to get better, and there’s nothing wrong with casting something to any (e.g. value :: any) if you know it’s fine at runtime but Luau doesn’t give you a good way to work around it.

Oh def will use strict mode then. I’ve already know how to use the basics of typecheckings just not the function test<T>(...: T): () stuff as I’ve haven’t really don’t understand them. Even after reading the typechecking docs 5 times lol

Well for that specific example function name<T>(...: T): () is a function with a generic type named T that takes only a variadic parameter of type T and returns nothing.

local function myFunction<T>(...: T): ()
    -- do something...
end

myFunction("this is a string", "this is also a string") -- T is string
myFunction(1, 2, 3) -- T is number
myFunction({}, {}) -- T is {}
myFunction(1, "this is a string") -- type error as number and string do not relate
1 Like

I was talking about the <T> which I should of specified, but just read the docs again and now it makes much more sense of what <T> does. Though thanks for the explanation though. :+1:

Also we been going off topic :skull:

Calling multiple functions

local function BindButton(name: string, origPos: UDim2)
    -- Creates a button and gives functionality to it
    -- For example, creating hover and click effects and binding the frame.
end

-- Examples
BindButton("Play", UDim2.new(0, 0.5, 0, 0.5)) -- Creates Play button and gives functionality to it.
BindButton("Settings", UDim2.new(0, 0.5, 0, 0.5)) -- Creates Settings button and gives functionality to it.
BindButton("Credits", UDim2.new(0, 0.5, 0, 0.5)) -- Creates Credits button and gives functionality to it.

Calling one function with table

local function BindButton(tab: {})
    -- Loops through 'tab'
    -- Creates a button and gives functionality to it
    -- For example, creating hover and click effects and binding the frame.
end

-- Example
BindButton({
    {
        ["Name"] = "Play",
        ["OrigPos"] = UDim2.new(0, 0.5, 0, 0.5),
    },
    {
        ["Name"] = "Settings",
        ["OrigPos"] = UDim2.new(0, 0.5, 0, 0.5),
    },
    {
        ["Name"] = "Credits",
        ["OrigPos"] = UDim2.new(0, 0.5, 0, 0.5),
    },
})

I know that and sorry I did not explain correctly.

I’m sorry but this isn’t what I’m trying to achieve. Please check the first quote.

I’m not doing this for readability, I made this post for performance.

Others, thank you for the little off-topic type checking tutorial :wink:

Actually, I found a solution. It is pretty much the combination of both methods, increasing both readability and performance.

local function doSomething(someTable: {})
    -- Perform the function using information from the table
end

for _, tab in pairs({
    {
        -- All the information for the function.
    }
}) do
    doSomething(tab)
end

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.