EthicsComputerCourses
Join training +91 90532 10052

Functions

Swift · Lesson 10 of 30 Beginner 6 min read Updated

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.

Swift
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()
Output
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.

Swift
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")
Output
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.

Swift
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)
Output
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.

Swift
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)
Output
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.

Swift
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))
Output
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 is name:; write greet(name: "Ananya"), or declare the parameter with _.
  • Trying to change a parameter. Parameters are constants; copy to a var inside the function, or use inout if the caller's value must change.
  • Missing & with inout. The call must be applyDiscount(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; inout parameters change the caller's variable with &.
  • Functions have types like (Int) -> Int and 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
Swift
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))
Output
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)?

2. What does an inout parameter allow?

3. What is the type of func double(_ x: Int) -> Int?

4. When can you leave out return?

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