Step 1 of 5 · Reading · ~3 min
Learn
Functions and Closures
Functions
A Swift function declares its parameter types and its return type, and the compiler holds you to both.
func area(width: Int, height: Int) -> Int {
return width * height
}
print(area(width: 5, height: 3))
//> 15
func, a name, a parameter list, -> and the return type, then the body. A function that
returns nothing simply omits the -> Type.
The thing that surprises everyone: argument labels
Notice the call site above. It is not area(5, 3) — it is area(width: 5, height: 3). Swift
requires the labels by default. They are part of the function's identity, not decoration.
Each parameter actually has two names: an argument label used by callers, and a parameter name used inside the body. When you write only one name, it serves as both.
func greet(to person: String) -> String {
return "Hello, \(person)!"
}
print(greet(to: "Alice"))
//> Hello, Alice!
to is what callers write; person is what the body uses. The call reads like a sentence and
the body reads like code — that is the whole point of the split.
Removing the label with _
For a function whose arguments need no explanation, an underscore suppresses the label:
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
print(add(3, 4))
//> 7
✗ Does not compile — the label was suppressed but the caller supplied one
func add(_ a: Int, _ b: Int) -> Int { return a + b }
add(a: 3, b: 4)
✓ Compiles
func add(_ a: Int, _ b: Int) -> Int { return a + b }
add(3, 4)
The rule is symmetric and strict: the call site must match the declaration exactly. Deleting an underscore from a signature breaks every existing call.
Default values
Give a parameter a default and callers may skip it:
func greet(name: String, greeting: String = "Hello") -> String {
return "\(greeting), \(name)!"
}
print(greet(name: "Alice"))
print(greet(name: "Bob", greeting: "Howdy"))
//> Hello, Alice!
//> Howdy, Bob!
Put parameters without defaults first — they are the ones that carry the meaning.
Implicit return
If the body is a single expression, the return keyword is optional:
func double(_ n: Int) -> Int { n * 2 }
print(double(21))
//> 42
This only works for a single expression. A body containing print(...) and nothing else does
not implicitly return anything, because print produces no value.
Returning more than one value
A tuple lets a function hand back several values at once, with names:
func minMax(_ xs: [Int]) -> (low: Int, high: Int) {
return (xs.min()!, xs.max()!)
}
let result = minMax([3, 8, 2])
print(result.low, result.high)
//> 2 8
Functions are values
Every function has a type, written the same way as its signature: add above has type
(Int, Int) -> Int. That means a function can be stored in a variable or handed to another
function — which is exactly what the next lesson builds on.
let op: (Int, Int) -> Int = add
print(op(10, 5))
//> 15
Your exercise
Fill in func square(_ n: Int) -> Int so it returns n * n, and let the starter's existing
print(square(n)) do the rest.
The mistake the grader catches is leaving the placeholder in place. The starter's body is
return 0, and because one visible test feeds 0 and expects 0, an untouched starter already
passes that one — a partial pass is not progress. The second trap is the underscore: if you
retype the signature as func square(n: Int) -> Int, the label comes back and the starter's own
square(n) call stops compiling. Change the body, not the signature. A hidden test passes -5
and expects 25, which n * n handles without any special case.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…