Functions in Swift: Parameters, Return Types, and Overloading
When Remy in Ratatouille needs to make soup, he doesn’t start from scratch every single time — he follows a recipe. You describe the steps once, and whenever you need soup, you just follow the same recipe with whatever ingredients you have on hand. In Swift, that recipe is called a function.
In this guide, you’ll learn how to define functions, pass data into them, and get results back. We’ll cover argument
labels, default parameters, variadic parameters, inout, tuples, and overloading. We won’t cover closures — they build
on functions and have their own dedicated post.
What You’ll Learn
- What Is a Function?
- Parameters and Return Types
- Argument Labels
- Default and Variadic Parameters
- Multiple Return Values
- Function Overloading
- Functions as Values
- Common Mistakes
- What’s Next?
What Is a Function?
A function is a reusable block of code that performs a specific task. You give it a name, and whenever you need that task done, you call the function by name instead of rewriting the same code.
Think of it like the Claw in Toy Story’s Pizza Planet. The Claw does one thing: reach down and grab a toy. You don’t need to know exactly how it works — you just press the button (call the function) and it does its job.
Here’s the simplest possible function:
func sayHello() {
print("Hello from Andy's room!")
}
sayHello()
Hello from Andy's room!
The keyword func declares a function. sayHello is its name. The parentheses () mean it takes no input. The curly
braces {} contain the code that runs when you call it.
Parameters and Return Types
Most functions need input data to work with. You provide input through parameters — variables listed inside the parentheses.
func greet(character: String) {
print("Welcome, \(character)!")
}
greet(character: "Woody")
greet(character: "Buzz")
Welcome, Woody!
Welcome, Buzz!
To send data back from a function, declare a return type after an arrow (->):
func motto(for character: String) -> String {
return "\(character) reporting for duty!"
}
let message = motto(for: "Buzz Lightyear")
print(message)
Buzz Lightyear reporting for duty!
Tip: If the function body is a single expression, you can omit the
returnkeyword:func double(_ number: Int) -> Int { number * 2 }
Argument Labels
Swift functions have two names for each parameter: an argument label (used when calling) and a parameter name (used inside the function body).
func move(character name: String,
to destination: String) {
print("\(name) moves to \(destination)")
}
move(character: "Woody", to: "Bonnie's house")
Woody moves to Bonnie's house
In character name: String, the word character is the argument label (visible at the call site) and name is the
parameter name (used inside the function body).
Omitting Argument Labels
Use an underscore (_) to let callers skip the label entirely:
func rescue(_ character: String) {
print("Rescuing \(character)!")
}
rescue("Buzz")
Rescuing Buzz!
Without the _, you’d have to write rescue(character: "Buzz"). The underscore makes the call site shorter when the
function name already makes the parameter’s purpose clear.
Default and Variadic Parameters
Default Parameter Values
Give a parameter a default value so callers can skip it when the default is fine:
func rateMovie(_ title: String, stars: Int = 5) {
print("\(title): \(stars) stars")
}
rateMovie("Up")
rateMovie("Cars 2", stars: 2)
Up: 5 stars
Cars 2: 2 stars
Variadic Parameters
A variadic parameter accepts zero or more values of the same type. Inside the function, they arrive as an array.
Declare one by adding ... after the type:
func rollCall(_ names: String...) {
for name in names {
print("\(name) is here!")
}
}
rollCall("Woody", "Buzz", "Jessie")
Woody is here!
Buzz is here!
Jessie is here!
inout Parameters
By default, function parameters are constants — you can’t change them. An inout parameter lets you modify a value
that lives outside the function:
func levelUp(_ score: inout Int) {
score += 10
}
var playerScore = 85
levelUp(&playerScore)
print(playerScore)
95
The & before playerScore signals that the function may modify this value. Use inout sparingly — returning a new
value is usually clearer and easier to reason about.
Multiple Return Values with Tuples
A tuple bundles multiple values into a single compound value. Functions can return tuples to send back more than one piece of data:
func movieStats(_ title: String)
-> (year: Int, rating: Double) {
switch title {
case "Toy Story":
return (year: 1995, rating: 8.3)
case "Up":
return (year: 2009, rating: 8.3)
default:
return (year: 0, rating: 0.0)
}
}
let stats = movieStats("Toy Story")
print("\(stats.year) — Rating: \(stats.rating)")
1995 — Rating: 8.3
You access tuple elements by their names (stats.year, stats.rating), making the code readable and self-documenting.
Apple Docs:
Functions— The Swift Programming Language
Function Overloading
Overloading means creating multiple functions with the same name but different parameter types or counts. Swift tells them apart based on the arguments you pass:
func describe(_ movie: String) {
print("Movie: \(movie)")
}
func describe(_ movie: String, year: Int) {
print("Movie: \(movie) (\(year))")
}
describe("Finding Nemo")
describe("Finding Nemo", year: 2003)
Movie: Finding Nemo
Movie: Finding Nemo (2003)
Swift chooses the right version automatically based on how you call it. This is useful when you want the same action with varying levels of detail.
Functions as Values
In Swift, functions are first-class citizens — you can store them in variables, pass them to other functions, and return them from functions, just like any other value:
func add(_ a: Int, _ b: Int) -> Int {
a + b
}
let operation = add
print(operation(3, 7))
10
This powerful concept becomes central when you learn about closures — anonymous functions you can pass around like any other value.
Common Mistakes
Forgetting the Return Type
// ❌ Won't compile — returning a value from a Void function
func fullName(first: String, last: String) {
return "\(first) \(last)"
}
// ✅ Declare the return type with ->
func fullName(first: String, last: String) -> String {
return "\(first) \(last)"
}
Missing Argument Labels at the Call Site
// ❌ Won't compile — missing the argument label
func greet(character: String) {
print("Hi, \(character)!")
}
// greet("Woody") // Error: missing argument label
// ✅ Include the label, or define with _ to omit it
func greet(character: String) {
print("Hi, \(character)!")
}
greet(character: "Woody")
What’s Next?
- Functions are reusable blocks of code defined with
func. - Parameters pass data in; return types send data back.
- Argument labels make call sites read like natural language.
- Default parameters provide fallback values; variadic parameters accept flexible input counts.
- Tuples let you return multiple values from one function.
- Function overloading gives the same name different behaviors based on parameter types.
Functions become even more powerful when you can create them on the fly and pass them around. Head to Post 11: Closures to learn about anonymous functions, capturing values, and trailing closure syntax.