Functions
A function is a named block of code that does one job. You have already called print, max and sorted. Now you will write your own. Functions let you write a piece of logic once, give it a clear name, and reuse it anywhere, which keeps programs short and easier to fix.
Swift functions have a feature you will not find in most languages: argument labels, which make a function call read like an English sentence. In this lesson you will learn labels, default values, returning several values, changing a caller's variable with inout, and treating functions as values.
Defining and calling a function
Start with func, the name, the parameters in brackets (each with a name and type), then -> and the return type. A function that returns nothing simply leaves out the arrow.
func greet(name: String) -> String {
return "Namaste, \(name)!"
}
print(greet(name: "Ananya"))
func area(length: Double, width: Double) -> Double {
length * width
}
print(area(length: 12, width: 10.5))
func printLine() {
print("----------")
}
printLine()Namaste, Ananya! 126.0 ----------
When a function body is a single expression, you can leave out return, as area does. Parameters are constants inside the function, so you cannot assign a new value to length. Notice 126.0: the result is a Double, and a Double with no fraction still prints with .0.
Argument labels and default values
Each parameter has an argument label, used when calling, and a parameter name, used inside the function. By default they are the same. Write a separate label before the name to make calls read well, or write _ to have no label at all. A parameter can also have a default value, which the caller may leave out.
func send(_ message: String, to person: String, from city: String = "Pune") {
print("\(message) to \(person) from \(city)")
}
send("Diwali greetings", to: "Meera")
send("Exam results", to: "Kabir", from: "Rohtak")Diwali greetings to Meera from Pune Exam results to Kabir from Rohtak
Read the call aloud: "send Diwali greetings to Meera from Pune". Inside the function, the code uses the clearer names person and city. Apple's API design guidelines recommend this style, so you will see it everywhere in Apple frameworks, for example names.joined(separator: ", ") and list.insert("x", at: 0).
Returning more than one value
Return a tuple to give back several values at once. Make the return type optional with ? when there might be no answer, such as for an empty list.
func minMax(of marks: [Int]) -> (lowest: Int, highest: Int)? {
guard var low = marks.first else { return nil }
var high = low
for mark in marks.dropFirst() {
low = min(low, mark)
high = max(high, mark)
}
return (low, high)
}
if let result = minMax(of: [67, 91, 45, 88]) {
print("Lowest \(result.lowest), highest \(result.highest)")
}
print(minMax(of: []) == nil)Lowest 45, highest 91 true
guard var low = marks.first unwraps the first mark into a variable, or returns nil for an empty array. The caller unwraps the result with if let and reads the tuple's parts by name. You will study if let and guard let in Optionals & Unwrapping.
Variadic and inout parameters
A variadic parameter, written Type..., accepts any number of values and arrives inside the function as an array. An inout parameter lets a function change a variable that belongs to the caller. The caller must write & before the variable, which makes the change obvious at the call site.
func average(_ numbers: Double...) -> Double {
guard !numbers.isEmpty else { return 0 }
return numbers.reduce(0, +) / Double(numbers.count)
}
print(average(72, 85, 90))
func applyDiscount(to price: inout Int, percent: Int) {
price -= price * percent / 100
}
var shoePrice = 2499
applyDiscount(to: &shoePrice, percent: 20)
print(shoePrice)82.33333333333333 2000
The average is 247 divided by 3, and a Double prints all its significant digits; format it with String(format: "%.2f", value) when showing it to users. The discount is 20 percent of 2,499 in whole rupees, which is 499, leaving 2,000. Use inout sparingly: a function that returns a new value is usually easier to understand.
Functions are values
In Swift, a function has a type, such as (Int) -> Int ("takes an Int, returns an Int"). You can store functions in constants and arrays, and pass them to other functions, just like numbers or strings.
func addGST(_ amount: Int) -> Int { amount * 118 / 100 }
func roundToTen(_ amount: Int) -> Int { (amount + 5) / 10 * 10 }
let steps: [(Int) -> Int] = [addGST, roundToTen]
var bill = 455
for step in steps {
bill = step(bill)
}
print(bill)
func factorial(_ n: Int) -> Int {
n <= 1 ? 1 : n * factorial(n - 1)
}
print(factorial(5))540 120
The bill of ₹455 becomes 536 with GST, then 540 after rounding to the nearest ten. factorial is recursive: it calls itself with a smaller number until it reaches 1. This idea, functions as values, is the basis of closures, map and filter, and SwiftUI's buttons, which you will meet in Closures.
Common mistakes
- Forgetting labels when calling.
greet("Ananya")does not compile when the label isname:; writegreet(name: "Ananya"), or declare the parameter with_. - Trying to change a parameter. Parameters are constants; copy to a
varinside the function, or useinoutif the caller's value must change. - Missing
&withinout. The call must beapplyDiscount(to: &shoePrice, percent: 20). - Ignoring a returned value. Swift warns when you call a function and do not use its result. Use the result, or assign it to
_if you truly do not need it.
Key points
- Declare functions with
func name(label param: Type) -> ReturnType { }. - Argument labels make calls readable;
_removes a label, and default values make arguments optional. - A single-expression body can leave out
return. - Return a tuple for several values, and an optional when there may be no result.
- Variadic parameters take any number of values;
inoutparameters change the caller's variable with&. - Functions have types like
(Int) -> Intand can be stored and passed like any value.
Exercise
Write a function splitBill(total:people:tipPercent:) that returns each person's share as a Double, with tipPercent defaulting to 10. Call it for a ₹1,800 dinner shared by 4 friends (default tip) and for ₹2,500 shared by 5 friends with a 0 percent tip, and print both results.
Show solution
func splitBill(total: Double, people: Int, tipPercent: Double = 10) -> Double {
let withTip = total + total * tipPercent / 100
return withTip / Double(people)
}
print(splitBill(total: 1800, people: 4))
print(splitBill(total: 2500, people: 5, tipPercent: 0))495.0 500.0
With a 10 percent tip, ₹1,800 becomes ₹1,980, and a quarter of that is 495. The second call passes tipPercent: 0, so the share is exactly 500.
Quick Quiz
1. How do you call func book(_ seat: String, for name: String)?
_ removes the first label, and the second parameter uses the label for.
2. What does an inout parameter allow?
inout writes the changed value back to the caller's variable.
3. What is the type of func double(_ x: Int) -> Int?
A function type lists the parameter types in brackets, then -> and the return type.
4. When can you leave out return?
Single-expression bodies return their value implicitly.
Learn Swift with a mentor
Free lessons get you started. Our Mobile App Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
