SkillByAIOpen interactive version →

Lesson 10 / 25

Functions and Argument Labels

Write functions with argument labels, defaults, inout and variadic parameters.

Readable call sites

Swift functions have argument labels that make calls read like sentences: move(from: a, to: b). Each parameter has an external label and an internal name (func send(_ message: String, to recipient: String)), and _ omits the label. Parameters can have default values, and variadic parameters accept several values (numbers: Int...). Parameters are constants by default; inout parameters let a function modify a caller's variable, passed with & at the call site. Functions are first-class: they can be stored in variables, passed as arguments and returned, with types written like (Int, Int) -> Int. Functions can be nested, and overloaded by parameter labels and types. Return values can be omitted in single-expression bodies. Mark functions whose results should not be ignored with @discardableResult only when ignoring is fine; by default the compiler warns about unused results. Follow the Swift API Design Guidelines: clarity at the point of use is more important than brevity.

Labels make calls read clearly

External labels describe each argument at the call site; internal names are used inside the function.

Figure 4.1 — Argument labels and parameter names.

Labels, defaults, variadics and inout

Call sites read naturally; inout changes the caller's variable.

func transfer(_ amount: Double, from source: String, to destination: String, note: String = "") -> String {
    "Moved \(amount) from \(source) to \(destination)" + (note.isEmpty ? "" : " (\(note))")
}

print(transfer(500, from: "savings", to: "current"))
print(transfer(200, from: "current", to: "wallet", note: "festival"))

func average(of numbers: Double...) -> Double {
    numbers.isEmpty ? 0 : numbers.reduce(0, +) / Double(numbers.count)
}
print(average(of: 70, 85, 91))

func applyDiscount(to price: inout Double, percent: Double) {
    price -= price * percent / 100
}
var price = 1000.0
applyDiscount(to: &price, percent: 10)     // price is now 900.0

let operation: (Double, Double) -> Double = (+)   // functions are values
print(operation(2, 3))

Name for the call site

Read the call aloud: remove(at: index) and insert(item, at: 0) read like English. If a call needs a comment to explain its arguments, better labels usually remove that need.

Quick check: How do you let a function modify a caller's variable in Swift?

  • Use a var parameter
  • Return a pointer
  • Declare the parameter inout and pass the argument with &
  • It is not possible
Answer

Declare the parameter inout and pass the argument with & — inout parameters write their final value back to the caller's variable.