How to use variadic parameters in Swift

Mar 03, 2024#swift#functions

In Swift, variadic parameters allow a function to accept a variable number of arguments of the same type. This is useful when you want to create a function that can take any number of arguments of a specific type without specifying the exact number of parameters in the function’s signature.

To declare a variadic parameter in Swift, you use three dots (...) after the parameter’s type. Here’s a basic example:

func sum(_ numbers: Int...) -> Int {
    var result = 0
    for number in numbers {
        result += number
    }
    return result
}

let total = sum(1, 2, 3, 4, 5)
print(total) // Output: 15

Inside the function, the variadic arguments are treated as an array of the specified type. You can access them using the usual array methods, like iterating through them using a loop.

When calling the function, you can pass any number of arguments of the specified type.

How many variadic parameters are allowed?

Before Swift 5.4, the ability to use multiple variadic parameters in functions was not available. You could only have one variadic parameter in a function. However, starting from Swift 5.4, you can now use multiple variadic parameters as long as all parameters following a variadic parameter have labels.

func summarizeGoals(times: Int..., players: String...) {
    let joinedNames = ListFormatter.localizedString(byJoining: players)
    let joinedTimes = ListFormatter.localizedString(byJoining: times.map(String.init))
    print("\(times.count) goals were scored by \(joinedNames) at the following minutes: \(joinedTimes)")
}

// Call the function with both sets of values
summarizeGoals(times: 18, 33, 55, 90, players: "Dani", "Jamie", "Roy")

// 4 goals were scored by Dani, Jamie, and Roy at the following minutes: 18, 33, 55, and 90

When is argument label required?

The first parameter that comes after a variadic parameter must have an argument label. The argument label makes it unambiguous which arguments are passed to the variadic parameter and which arguments are passed to the parameters that come after the variadic parameter.

func calculateAverage(_ numbers: Int..., dividedBy divisor: Int) -> Double {
    let sum = numbers.reduce(0, +)
    let average = Double(sum) / Double(numbers.count)
    return average / Double(divisor)
}

// Example usage
let averageResult = calculateAverage(10, 20, 30, 40, dividedBy: 5)
print("Average result: \(averageResult)")

// Average result: 5.0

In this example: The numbers parameter is variadic, allowing us to pass any number of integers. The divisor parameter is non-variadic and has an argument label (dividedBy), making it clear which value is used for division.

Can variadic parameters be omitted?

Variadic parameters in Swift can be omitted when calling a function because they default to an empty array ([]). This behavior ensures that even if you don’t explicitly provide any values for the variadic parameter, the function will still execute correctly.

func sumOfIntegers(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}

// Call the function with no arguments for the variadic parameter
let result = sumOfIntegers()
print("Sum of integers: \(result)")

// Sum of integers: 0

Why not using an array directly?

Using variadic parameters often leads to cleaner and simpler syntax, especially when dealing with a small number of arguments. It eliminates the need for square brackets and makes the code more straightforward.

Variadic parameters can be beneficial in logging or debugging scenarios where you want to print or process a variable number of values without the need to create an array explicitly.

// Using variadic parameters
printValues(1, 2, 3)

// Equivalent using an array
printValuesFromArray([1, 2, 3])

When dealing with a small number of values, using variadic parameters can be more efficient than creating an array. It avoids the overhead of array creation and the need to allocate memory for a separate data structure.