func name(label paramName: Type) declares a parameter with an external argument label (what appears at the call site) distinct from its internal parameter name (what the function body actually uses) — by default, a parameter's first name serves as both, but writing two names lets a call read naturally in English (move(to: point)) while the body still uses a short internal name. An underscore (_) as the label suppresses it entirely, letting a call omit that argument's name, which is idiomatic when the parameter's meaning is already obvious from context.
Default behavior: the parameter name doubles as the label
Without any special syntax, greet(name:) both the call site and the function body use "name" — the simplest, default case.
func greet(name: String) {
print("Hello, \(name)!")
}
greet(name: "Alice") // "name" is both the label AND the internal parameter nameTwo different names: label at the call site, name in the body
The call reads naturally as move(to: destination) — close to an English sentence — while the function body uses the shorter, more convenient point internally. These are genuinely two separate identifiers for the same parameter.
func move(to point: (x: Int, y: Int)) {
print("Moving to \(point.x), \(point.y)") // uses 'point' internally
}
move(to: (x: 10, y: 20)) // caller writes 'to:' — the external labelSuppressing the label entirely with _
An underscore as the label means the call omits any name for that argument at all — idiomatic when a parameter's meaning is already obvious, like the second argument to a two-number add function.
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
add(3, 4) // no labels at all — reads like a typical math function call