Variadic Functions

Accepting an infinite number of arguments

by Halalaluyafail3

Author Avatar

Including an ellipsis at the end of a parameter list makes the function a Variadic function.

local function a(b,c,...)

end

Whenever you use an ellipsis in a Variadic function it represents all extra arguments. Wrapping the ellipsis in parenthesis will force it to the first extra argument or nil.

Using 'select'

One of the built in functions, can be used to either get the amount of arguments passed, or get the Xth argument and above (negative number will get the last arguments, aka a negative index)

-- "#" option is used for length
print(select("#",1,2,3,4,nil))
--> 5
print(select(3,1,2,3,4,nil))
--> 3  4  nil
print(select(-2,1,2,3,4,nil))
--> 4  nil

Using the vararg expression

The vararg expression can be used like any other variable name (expect when indexing/calling, to directly index or call the first value of the vararg expression requires wrapping it in parenthesis). However, varargs can't be used inside of inner functions. To use the variable arguments inside of an inner function they must be saved to some other data structure to hold the values.

local function test(...)
    local first,second,third = ... -- can get arguments like this
    print(first,second,third)
    print(...)
    print("amount of args:",select("#",...))
    print("last 3 arguments:",select(-3,...))
    print("excluding first 2 arguments:",select(3,...))
    return select(-1,...) -- return last argument
end
local last = test(1,2,3,4,5,6,7,8,9)
print("last argument:",last)
--> 1 2 3
--> 1 2 3 4 5 6 7 8 9
--> amount of args: 9
--> last 3 arguments: 7 8 9
--> exclusing first 2 arguments: 3 4 5 6 7 8 9
--> last argument: 9

Passing something after a vararg expression

Whenever you pass something after a list of values, the list of values gets forced to a single value (or nil if there is no values).

ex:

local function test(...)
    print(select("#",...))
    print(select("#",...,nil))
    print(select("#",(...)))
end
test(1,2,3,4,5)
--> 5
--> 2
--> 1

To get around this, tables (or another data structure) must be used.

local function test(...)
    local packed,length = {...},select("#",...)
    local lengthP1 = length+1
    packed[lengthP1] = 6
    return table.unpack(packed,1,lengthP1)
end
print(test(1,2,3,4,5))
--> 1 2 3 4 5 6

Getting the nth argument

Often with a vararg, you will want to get the nth argument. This can be be done with the previously mentioned 'select'.

local function test(arg,...)
    local narg = select(arg,...)
    print(narg)
end
test(2,"a","b","c")
--> b
test(5,5,4,3,2,1)
--> 1
test(-1,5,4,3,2,1)
--> 1

Example

A sum function which will add all arguments passed.

local function sum(...)
    local args = select("#",...)
    local sum = 0
    for i=1,args do
        sum = sum + select(i,...)
        -- in this case the first result of select is used
    end
    return sum
end
print(sum(1,2,3))
--> 6
print(sum(1,-1,0))
--> 0