Functions
This guide explains how to define, call, and use functions in Swift. Functions are reusable blocks of code that perform specific tasks. They can take inputs (parameters), return outputs, and be used in various ways.
Defining and Calling Functions
Functions are defined using the func keyword. You can specify parameters (inputs) and a return type (output).
Here's a basic example: A function that takes a username and returns a welcome message.
func welcome(user: String) -> String {
let message = "Welcome, " + user + "!"
return message
}Call it like this:
print(welcome(user: "Alex"))
// Prints "Welcome, Alex!"
print(welcome(user: "Jordan"))
// Prints "Welcome, Jordan!"The function name is welcome(user:). Arguments must match the parameter order.
You can shorten it by combining the return:
func welcomeBack(user: String) -> String {
return "Welcome back, " + user + "!"
}
print(welcomeBack(user: "Alex"))
// Prints "Welcome back, Alex!"Function Parameters and Return Values
Swift functions are flexible with parameters and returns.
Functions Without Parameters
No inputs needed? Just define it without parameters.
func sayHello() -> String {
return "Hello there!"
}
print(sayHello())
// Prints "Hello there!"Functions With Multiple Parameters
Pass multiple values, separated by commas.
This function takes a name and a flag for previous welcome:
func welcome(user: String, previouslyWelcomed: Bool) -> String {
if previouslyWelcomed {
return welcomeBack(user: user)
} else {
return welcome(user: user)
}
}
print(welcome(user: "Sam", previouslyWelcomed: true))
// Prints "Welcome back, Sam!"Functions Without Return Values
No return? Omit the -> and type. It implicitly returns Void.
func welcome(user: String) {
print("Welcome, \(user)!")
}
welcome(user: "Pat")
// Prints "Welcome, Pat!"You can ignore returns from functions that have them:
func printAndLength(text: String) -> Int {
print(text)
return text.count
}
func printOnly(text: String) {
let _ = printAndLength(text: text)
}
printAndLength(text: "good day")
// Prints "good day" and returns 8
printOnly(text: "good day")
// Prints "good day" (ignores return)Functions with Multiple Return Values
Use tuples to return multiple values.
This finds min and max in an array:
func findMinMax(numbers: [Int]) -> (min: Int, max: Int) {
var minVal = numbers[0]
var maxVal = numbers[0]
for num in numbers[1..<numbers.count] {
if num < minVal {
minVal = num
} else if num > maxVal {
maxVal = num
}
}
return (minVal, maxVal)
}
let results = findMinMax(numbers: [5, -2, 10, 1, 7])
print("Min: \(results.min), Max: \(results.max)")
// Prints "Min: -2, Max: 10"Optional Tuple Return Types
Make the tuple optional (?) if it might be nil.
func findMinMax(numbers: [Int]) -> (min: Int, max: Int)? {
if numbers.isEmpty { return nil }
// ... (same logic as above)
return (minVal, maxVal)
}
if let results = findMinMax(numbers: [5, -2, 10, 1, 7]) {
print("Min: \(results.min), Max: \(results.max)")
}
// Prints "Min: -2, Max: 10"Functions With an Implicit Return
Single-expression functions can omit return.
func message(for user: String) -> String {
"Hi, " + user + "!"
}
print(message(for: "Lee"))
// Prints "Hi, Lee!"Function Argument Labels and Parameter Names
Parameters have argument labels (for calls) and names (for body). By default, they're the same.
func example(first: Int, second: Int) {
// Use first and second inside
}
example(first: 1, second: 2)Specifying Argument Labels
Customize labels for readability.
func greet(person: String, from city: String) -> String {
return "Hi \(person)! Nice to see you from \(city)."
}
print(greet(person: "Kim", from: "Seattle"))
// Prints "Hi Kim! Nice to see you from Seattle."Omitting Argument Labels
Use _ to omit labels.
func example(_ first: Int, second: Int) {
// ...
}
example(1, second: 2)Default Parameter Values
Assign defaults to optional parameters.
func example(noDefault: Int, withDefault: Int = 10) {
// ...
}
example(noDefault: 5, withDefault: 8) // withDefault=8
example(noDefault: 5) // withDefault=10Put non-defaults first.
Variadic Parameters
Use ... for variable arguments (as array inside).
This averages numbers:
func average(_ values: Double...) -> Double {
var sum: Double = 0
for val in values {
sum += val
}
return sum / Double(values.count)
}
print(average(2, 4, 6))
// Prints 4.0Multiple variadics possible; label params after first.
In-Out Parameters
Use inout to modify passed variables. Pass with &.
func swapValues(_ x: inout Int, _ y: inout Int) {
let temp = x
x = y
y = temp
}
var num1 = 4
var num2 = 9
swapValues(&num1, &num2)
print("num1: \(num1), num2: \(num2)")
// Prints "num1: 9, num2: 4"No defaults or variadics with inout.
Function Types
Functions have types like (Int, Int) -> Int.
func plus(_ a: Int, _ b: Int) -> Int { return a + b }
func times(_ a: Int, _ b: Int) -> Int { return a * b }Type: (Int, Int) -> Int
Using Function Types
Assign to variables:
var operation: (Int, Int) -> Int = plus
print(operation(3, 4)) // 7
operation = times
print(operation(3, 4)) // 12Infer type:
let anotherOp = plusFunction Types as Parameter Types
Pass functions:
func runOp(_ op: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print(op(a, b))
}
runOp(plus, 3, 4) // 7Function Types as Return Types
Return functions:
func increment(_ num: Int) -> Int { return num + 1 }
func decrement(_ num: Int) -> Int { return num - 1 }
func selectOp(decrease: Bool) -> (Int) -> Int {
return decrease ? decrement : increment
}
var value = 5
let adjust = selectOp(decrease: value > 0)
while value != 0 {
value = adjust(value)
print(value)
}Nested Functions
Define functions inside others for encapsulation.
func selectOp(decrease: Bool) -> (Int) -> Int {
func increment(num: Int) -> Int { return num + 1 }
func decrement(num: Int) -> Int { return num - 1 }
return decrease ? decrement : increment
}