DEV Community

Gamya
Gamya

Posted on

Swift Functions — Default Parameters

In the last article, we touched on default parameters with the findDirections example. This time, let's slow down and really dig into why they exist, when to reach for them, and a few places they show up that you might not expect. 🍥

The Problem Default Parameters Solve

Imagine you're writing a function for an anime training montage generator 🥋:

func startTraining(student: String, intensity: String, withMusic: Bool) {
    print("\(student) begins training at \(intensity) intensity!")
    if withMusic {
        print("🎵 Dramatic music plays 🎵")
    }
}

startTraining(student: "Naruto", intensity: "extreme", withMusic: true)
Enter fullscreen mode Exit fullscreen mode

Now imagine 90% of your training montages are "extreme intensity, with music" — because of course they are. Calling this function with all three parameters every single time gets repetitive fast.

This is exactly the gap default parameters fill: let the common case be short, and the unusual case still possible.

func startTraining(student: String, intensity: String = "extreme", withMusic: Bool = true) {
    print("\(student) begins training at \(intensity) intensity!")
    if withMusic {
        print("🎵 Dramatic music plays 🎵")
    }
}

startTraining(student: "Naruto")
startTraining(student: "Sakura", intensity: "moderate")
startTraining(student: "Rock Lee", intensity: "extreme", withMusic: false)
Enter fullscreen mode Exit fullscreen mode

All three calls are valid. The first uses both defaults, the second overrides just intensity, and the third overrides both extra parameters. 🎉

The Rule: Defaults Go Last (Usually)

Swift doesn't strictly require default parameters to come last, but it's strongly recommended — and here's why.

func describeCharacter(name: String, power: String = "unknown", age: Int) {
    print("\(name) is \(age) years old with \(power) power.")
}
Enter fullscreen mode Exit fullscreen mode

This compiles, but calling it gets awkward:

describeCharacter(name: "Goku", age: 30)
Enter fullscreen mode Exit fullscreen mode

This actually works fine here because both power and age have labels — Swift matches by label, not position, for parameters after the first. But the moment you mix in unlabeled parameters (using _), putting a default in the middle can create confusing or even invalid call sites. The convention exists to keep things predictable: put your "always changes" parameters first, and your "rarely changes" parameters with defaults at the end.

func describeCharacter(name: String, age: Int, power: String = "unknown") {
    print("\(name) is \(age) years old with \(power) power.")
}

describeCharacter(name: "Goku", age: 30)
describeCharacter(name: "Goku", age: 30, power: "Kamehameha")
Enter fullscreen mode Exit fullscreen mode

Much cleaner. ✨

Default Parameters Are Everywhere in Swift's Standard Library

This is the part that clicked for me once I started noticing it: Swift itself uses default parameters constantly, and once you know to look for them, a lot of "magic" behavior makes more sense.

Example 1 — removeAll(keepingCapacity:)

var characters = ["Lana", "Pam", "Ray", "Sterling"]
characters.removeAll()
// same as:
characters.removeAll(keepingCapacity: false)
Enter fullscreen mode Exit fullscreen mode

keepingCapacity defaults to false, because most of the time when you clear an array, you're done with that memory. But if you're about to refill it with a similar number of items, removeAll(keepingCapacity: true) avoids Swift having to re-allocate memory from scratch.

Example 2 — String comparison

let name = "naruto"
name.compare("Naruto") // default options
name.compare("Naruto", options: .caseInsensitive)
Enter fullscreen mode Exit fullscreen mode

compare(_:options:) has a default empty options set, so the simple case (case-sensitive comparison) needs no extra arguments — but case-insensitive comparison is one parameter away when you need it.

Example 3 — print() itself!

You've been using default parameters this whole time without realizing it:

print("Hello")
print("Hello", separator: " ", terminator: "\n")
Enter fullscreen mode Exit fullscreen mode

print has default values for separator (a single space) and terminator (a newline). That's why print("a", "b", "c") outputs a b c with a line break at the end — and why you can override terminator: "" if you want multiple prints to appear on the same line.

print("Loading", terminator: "")
print("...", terminator: "")
print("done!")
// Output: Loading...done!
Enter fullscreen mode Exit fullscreen mode

A Quick Gotcha: Defaults Don't Mean "Optional"

It's easy to mentally lump default parameters together with optionals (Int?, String?), but they're solving different problems:

  • A default parameter means "if the caller doesn't specify this, use this fallback value." The parameter inside the function is never nil — it's always a real value (either what was passed, or the default).
  • An optional means "this value might genuinely not exist, and the function needs to handle that."
// Default parameter — always has a real value inside the function
func greet(name: String = "friend") {
    print("Hello, \(name)!")
}

// Optional — might be nil, function must check
func greet(name: String?) {
    if let name = name {
        print("Hello, \(name)!")
    } else {
        print("Hello, friend!")
    }
}
Enter fullscreen mode Exit fullscreen mode

Both greet() calls above can produce "Hello, friend!" — but they get there very differently, and mixing up which one you need can lead to unnecessary if let checks when a default parameter would've done the job.

Wrap Up

Default parameters are one of those features that feel small at first but show up everywhere once you start looking — both in your own code and throughout Swift's standard library. The core idea is simple: make the common case effortless, while keeping the door open for customization.

A good rule of thumb when designing your own functions: if you find yourself passing the same value to a parameter 90% of the time, that's a strong candidate for a default. 🍥


I know these Swift concepts well from hands-on practice — I use AI to help draft and organize my explanations, and every example and structure choice is something I've reviewed and stand behind.


Top comments (1)

Collapse
 
technogamerz profile image
𝓣𝓱𝓮𝓛𝓪𝔃𝔂 𝓰𝓲𝓻𝓵 ◕⁠‿⁠◕

Episode 28 complete ✅ 💪🏻