Functions in Swift
Learn how to define and call functions in Swift, including argument labels, default and variadic parameters, in-out parameters, recursion, and first-class closures with Docker-ready examples
Functions are the primary building blocks of reusable logic in Swift. A function packages a piece of behavior behind a name, accepts typed inputs, and produces a typed output. Swift’s static, strong, and inferred type system means the compiler verifies that every call site passes the right argument types and uses the return value correctly.
What sets Swift functions apart is their expressiveness. Functions support argument labels that make call sites read like prose, default parameter values that reduce overloads, variadic parameters for flexible arity, and in-out parameters for the rare cases where you need to mutate a caller’s variable. Just as importantly, Swift is a multi-paradigm language: functions are first-class values. You can store them in variables, pass them as arguments, and return them from other functions — the foundation of Swift’s functional style.
In this tutorial you’ll learn how to define and call functions, control how parameters are labeled and defaulted, return multiple values with tuples, write recursive functions, and treat functions as values using closures and higher-order functions like map, filter, and reduce.
Defining and Calling Functions
A function is declared with the func keyword, a name, a parenthesized parameter list, and an optional return type introduced by the -> arrow. Inside the body, return produces the result. Functions with no return type simply omit the arrow.
Create a file named functions_basics.swift:
| |
By default, Swift uses each parameter’s name as its argument label at the call site, which is why you write add(a: 3, b: 4). This self-documenting style is idiomatic Swift.
Argument Labels, Defaults, Variadics, and In-Out
Swift gives you fine-grained control over parameters. You can specify a separate external argument label (or suppress it with _), provide default values, accept a variable number of arguments with a variadic parameter (...), and allow a function to modify a caller’s variable using inout.
Create a file named parameters.swift:
| |
Note the & before score: Swift requires you to be explicit at the call site when a function can mutate one of your variables.
Recursion, Tuple Returns, and Scope
Functions can call themselves (recursion) and can return several values at once by returning a tuple. Swift also has clear scoping rules: a variable declared inside a function is local to it, while variables declared at the top level are global.
Create a file named recursion_scope.swift:
| |
Returning a named tuple lets callers access results by meaningful names (bounds.min, bounds.max) instead of positional indices.
Functions as Values: Closures and Higher-Order Functions
Because Swift is also a functional language, functions are first-class values. A function can be passed as an argument, stored in a constant, or returned from another function. Anonymous functions are called closures, written with the { ... in ... } syntax, and they can capture values from their surrounding scope. Swift’s collection types provide higher-order functions like map, filter, and reduce that take closures.
Create a file named higher_order.swift:
| |
The $0 shorthand refers to the first (and here only) closure argument, letting you write concise transformations like numbers.map { $0 * 2 }.
Running with Docker
You can compile and run every example with the official Swift image — no local toolchain required.
| |
Expected Output
Running functions_basics.swift:
Hello from a function!
3 + 4 = 7
Welcome, Swift!
Running parameters.swift:
Hello, Ada!
A medium coffee with 1 shot(s)
A large coffee with 2 shot(s)
Total: 15
Doubled score: 42
Running recursion_scope.swift:
5! = 120
Min: 1, Max: 11
Added 10
Added 5
Global count: 15
Running higher_order.swift:
applyTwice square 3 = 81
addOne(10) = 11
Doubled: [2, 4, 6, 8, 10, 12]
Evens: [2, 4, 6]
Sum: 21
addFive(20) = 25
Key Concepts
funcdeclares a function with typed parameters and an optional->return type; the compiler enforces types at every call site.- Argument labels make calls readable — Swift uses the parameter name as the label by default, lets you supply a separate external label, or suppress the label with
_. - Default and variadic parameters reduce the need for overloads: omit defaulted arguments, and pass any number of values to a
Type...parameter. - In-out parameters (
inout) let a function mutate a caller’s variable, but you must opt in explicitly with&at the call site. - Tuples return multiple values at once, and naming the tuple elements lets callers read results by name instead of position.
- Recursion is fully supported — a function may call itself, as long as it has a base case to terminate.
- Functions are first-class values — store them in constants, pass them as arguments, and return them; closures (
{ ... in ... }) are anonymous functions that capture surrounding state. - Higher-order functions like
map,filter, andreduceexpress transformations declaratively, reflecting Swift’s functional paradigm alongside its object-oriented and protocol-oriented styles.
Comments
Loading comments...
Leave a Comment