What does ... mean in a function?

I’ve seen other modules and scripts contain … in their function.

What I mean
function API:ConnectMouseLeft(Target,...)

What does it do? Will it do something bad to my game?

1 Like

... signifies variable arguments in functions. To elaborate further, some functions may accept unlimited arguments such as print and since it’s not very practical to write out thousands of parameters, ... was created to solve this problem.

With the code you provided it’s impossible to know the behavior of your script since you’re just declaring a new function and some parameters without the actual function code.

4 Likes

Sometimes, you may have to redefine ... as a variable to access it, however you can get around that by using the select() core function.

If you wanted to get how many it holds (#) then you can do:

select("#", ...)

Accessing it may require you to redefine it though.

3 Likes

Correction to be made here: you do not need to “redefine” variable arguments from a function because they aren’t given a definition in the first place. The act of collecting the variable arguments in order to use them is called marshaling. This can be done two ways: table.pack and wrapping them with a table constructor. The former is a newer and more updated method over the latter.

local function marshalVarargs(...)
    local methodOld = {...}
    local methodNew = table.pack(...)
end
3 Likes

table.pack also creates field n which stores the amount of arguments received in table.pack. (if you never use the n field, don’t use pack, and certainly don’t use it just because it is newer or more updated)

i.e

local function pack(...)
    return {n=select("#",...),...}
end

If you have access to the ... it is usually better to just use select to get this.

local args,length = {...},select("#",...)

Also, if you can avoid packing the variable arguments into a table, that will probably help. (usually you can)

1 Like

Ok people stop posting. I get it :grinning:

I don’t recommend doing what you’re doing.

I’m going off of the recommendation of this post by zeuxcg in Release Notes 394 not to use select and to marshal the legacy way. Newer or more updated methods are meant to be used in a lot of circumstances.

table.pack is recommended for use due to its convenience and the way it removes obscurity from what you are doing (select has been noted to be obscure). It is also faster than marshaling and computing the size alone, wherein nil arguments can upset the array size calculation. I mean you’re comparing

local args = table.pack(...)

to both

local function pack(...)
    return {n = select("#", ...), ...}
end

local args = pack(...)

and

local length, args = select("#", ...), {...}

Not using the n field of table.pack is no excuse not to use table.pack. It is also, in this scenario, canonically correct to use it over reinventing the wheel yourself for something provided by the engine.

You can… but then there’s no real use in varargs for that scenario? I can’t think of any reason why you would need varargs if you aren’t handling an arbitrary amount or type of arguments nor a situation where you can access them without packing them. That’s unless you’re using select.


@IUClDS It’s not necessarily to answer your question anymore (it already has been) but more to have discussion about programming. So long as there’s still helpful comments to offer to discussion, I think it’s fine to keep posting.

Just stop changing the solution frequently, since the first two posts answered it originally and we’re just following up with discussion. :sweat_smile:

1 Like