# Functions and Argument Labels — Swift

Source: https://www.skillbyai.com/en/swift/fn-functions

> 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.

![A function box with three input arrows, each tagged with an outside label and an inside label.](assets/figures/swift/section-4-map.svg) — Figure 4.1 — Argument labels and parameter names.

## Labels, defaults, variadics and inout

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

```swift
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.

**Quiz:** How do you let a function modify a caller's variable in Swift?

- [ ] Use a var parameter
- [ ] Return a pointer
- [x] 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.
