Swift Argument Labels and Default Values Explained
Swift functions are designed to read clearly at the call site, and two features that make that possible are argument labels and default values. In this article, you will learn what argument labels are, how they differ from parameter names, how default values reduce repetitive code, and how to avoid common errors when calling or declaring functions.
Quick answer: In Swift, an argument label is the name you use when calling a function, while the parameter name is the name used inside the function body. A default value lets a parameter be omitted during a call because Swift automatically supplies a predefined value.
Difficulty: Beginner
Helpful to know first: basic Swift syntax, how to declare and call simple functions, and common value types like String, Int, and Bool.
1. What Is Argument Labels & Default Values?
Argument labels and default values are part of Swift function parameter design. They help make function calls more readable and more flexible.
- Argument labels are the names written at the call site, such as from: or to:.
- Parameter names are the names used inside the function body.
- Default values let you skip an argument when calling a function if a sensible default already exists.
- These features make code easier to read and help functions behave like clear sentences.
- Swift intentionally distinguishes between how a function is called and how it is implemented.
For example, a function call like sendMessage(to: "Ava") is easier to understand than a call with unlabeled values. Swift treats that clarity as an important part of API design.
These features are also commonly confused with each other. An argument label is not the same thing as the local parameter name, and a default value does not make a parameter optional in the type-system sense. You will see those differences throughout the article.
2. Why Argument Labels & Default Values Matters
Good function design matters because functions are used everywhere in Swift. If a function call is hard to read, every place that uses it becomes harder to understand.
Argument labels matter because they:
- make calls read more naturally
- show the meaning of each argument
- reduce confusion when multiple parameters have the same type
- help prevent mistakes caused by positional guessing
Default values matter because they:
- reduce repeated arguments
- let you provide sensible behavior without forcing callers to specify every detail
- simplify APIs by avoiding multiple very similar overloads
- make common cases short and advanced cases still possible
You should use argument labels when they improve readability. You should use default values when one value is the normal choice in most calls. You should avoid default values when they hide behavior that needs to be explicit or when several defaults make a function call ambiguous to the reader.
3. Basic Syntax or Core Idea
Declaring a function with an argument label
In Swift, each parameter can have an external name for callers and a local name for use inside the function body.
func greet(person name: String) -> String {
return "Hello, \(name)!"
}Here, person is the argument label used by the caller, and name is the parameter name used inside the function.
let message = greet(person: "Mia")
print(message)The call site reads clearly because the label describes the role of the value.
Omitting an argument label with an underscore
If you do not want a label at the call site, use an underscore.
func square(_ number: Int) -> Int {
return number * number
}let result = square(4)
print(result)This is useful when the meaning is already obvious from the function name.
Adding a default value
A parameter can provide a value that Swift will use automatically if the caller leaves that argument out.
func greet(person name: String, politely: Bool = true) -> String {
if politely {
return "Hello, \(name)."
} else {
return "Hey, \(name)!"
}
}You can call this function with or without the second argument.
print(greet(person: "Mia"))
print(greet(person: "Mia", politely: false))The first call uses the default value. The second call overrides it.
4. Step-by-Step Examples
Example 1: A single labeled parameter
This example shows the simplest case where the label helps the call read clearly.
func openAccount(for customerName: String) {
print("Opening account for \(customerName)")
}
openAccount(for: "Jordan")The label for makes the call more expressive than a plain unlabeled string.
Example 2: Different external and internal names
Sometimes the best call-site label is not the best local variable name. Swift lets you choose both.
func calculateArea(width w: Double, height h: Double) -> Double {
return w * h
}
let area = calculateArea(width: 5.0, height: 3.0)
print(area)Callers see descriptive labels, while the function body uses short local names.
Example 3: Omitting a label where the function name is enough
For some mathematical or obvious operations, a label would add noise instead of clarity.
func repeatText(_ text: String, count: Int) -> String {
return String(repeating: text, count: count)
}
let banner = repeatText("*", count: 10)
print(banner)The first argument is obvious from the function name, but the second argument benefits from a label because count: explains the meaning of the integer.
Example 4: A default value for common behavior
This example shows how default values make the common case shorter.
func createUser(name: String, isAdmin: Bool = false) {
print("User: \(name), admin: \(isAdmin)")
}
createUser(name: "Lena")
createUser(name: "Sam", isAdmin: true)Most users are probably not administrators, so false is a sensible default.
Example 5: Multiple defaults in one function
Default values can be used for more than one parameter, but they should still keep the call understandable.
func connect(to host: String, port: Int = 443, useHTTPS: Bool = true) {
print("Connecting to \(host) on port \(port), HTTPS: \(useHTTPS)")
}
connect(to: "example.com")
connect(to: "localhost", port: 8080, useHTTPS: false)This approach works well when the defaults are obvious and commonly needed.
5. Practical Use Cases
- Building helper functions where labels make the purpose of each value clear, such as move(from:to:).
- Creating networking or file utility functions where one or two settings usually stay the same.
- Designing reusable app logic, such as user creation, formatting, sorting, or filtering helpers.
- Replacing several overloaded functions with one function that uses default parameter values.
- Improving APIs that take multiple values of the same type, such as coordinates, ranges, or names.
- Making business logic easier to read in team codebases, where self-documenting calls reduce confusion.
6. Common Mistakes
Mistake 1: Calling a function without the required argument label
In Swift, labels are part of the function signature at the call site. If a parameter has an argument label, you must use it when calling the function.
Problem: This call leaves out a required label, so Swift reports an error such as Missing argument label 'person:' in call.
func greet(person name: String) {
print("Hello, \(name)")
}
greet("Ava")Fix: Use the required label exactly as the function declaration defines it.
func greet(person name: String) {
print("Hello, \(name)")
}
greet(person: "Ava")The corrected version works because the call matches the function's required external parameter name.
Mistake 2: Using the internal parameter name at the call site
Beginners often confuse the internal parameter name with the argument label. Only the external label belongs in the function call.
Problem: This code uses the local name name instead of the external label person, which causes an error such as Incorrect argument label in call or Extraneous argument label depending on the declaration.
func greet(person name: String) {
print("Hello, \(name)")
}
greet(name: "Ava")Fix: Call the function with the external label and reserve the internal name for use inside the function body.
func greet(person name: String) {
print("Hello, \(name)")
}
greet(person: "Ava")The corrected version works because Swift distinguishes between the call-site label and the local parameter name.
Mistake 3: Supplying a label when the function uses an underscore
An underscore means the argument has no label at the call site. If you add one anyway, the call does not match the function declaration.
Problem: This function explicitly omits the first label, so using one causes an error such as Extraneous argument label 'number:' in call.
func square(_ number: Int) -> Int {
return number * number
}
let result = square(number: 5)Fix: Remove the label when the parameter is declared with an underscore.
func square(_ number: Int) -> Int {
return number * number
}
let result = square(5)The corrected version works because the call matches the unlabeled parameter definition.
Mistake 4: Assuming a default value makes the parameter optional
A parameter with a default value can be omitted, but its type is still whatever the function declares. It is not automatically an optional type.
Problem: This code treats isAdmin as though it were a Bool?, but the parameter type is still Bool.
func createUser(name: String, isAdmin: Bool = false) {
if isAdmin == nil {
print("No admin value provided")
}
}Fix: Use the parameter as its declared type. If you truly need nil as a distinct state, declare an optional parameter instead.
func createUser(name: String, isAdmin: Bool = false) {
if isAdmin {
print("Create admin user for \(name)")
} else {
print("Create regular user for \(name)")
}
}The corrected version works because default values provide fallback behavior without changing the parameter's type.
7. Best Practices
Use labels to make calls read like clear phrases
The best argument labels improve readability at the call site. Favor labels that explain the role of the value.
// Less clear
func transfer(_ amount: Double, _ account: String) {
print("Transfer \(amount) to \(account)")
}
// Preferred
func transfer(amount: Double, to account: String) {
print("Transfer \(amount) to \(account)")
}The preferred version is easier to understand because the call explains what each value means.
Choose default values only for genuinely common cases
A default value should represent the normal behavior, not a surprising shortcut.
// Less helpful if most calls override it
func saveReport(format: String = "xml") {
print("Saving as \(format)")
}
// Better if this is the real common case
func saveReport(format: String = "pdf") {
print("Saving as \(format)")
}This matters because defaults should reduce work, not force callers to keep overriding a poor choice.
Do not remove labels unless the meaning is obvious
Using _ can make function calls shorter, but too many unlabeled arguments make code harder to read.
// Less preferred
func move(_ x: Int, _ y: Int) {
print("Move to \(x), \(y)")
}
// Preferred
func move(toX x: Int, y yValue: Int) {
print("Move to \(x), \(yValue)")
}The preferred version gives more context, especially when many calls appear across a large codebase.
8. Limitations and Edge Cases
- Argument labels are part of how a function is called, so changing them can break existing code that depends on the old call syntax.
- Default values are evaluated when omitted, but they do not create multiple stored versions of the function. They simply let the compiler fill in missing arguments.
- A default value does not make the parameter optional. If you need the distinction between “not provided” and a real value, use an optional parameter or redesign the API.
- Too many parameters with default values can make calls confusing because readers may not know which behavior was explicitly chosen and which was inherited from defaults.
- When several parameters have the same type, omitting labels can make calls difficult to understand and easy to misuse.
- Functions with defaults can sometimes overlap conceptually with overloaded functions. Even when both approaches compile, default values are often simpler if the behavior is closely related.
- If a function seems “not working” after you rename a label, the issue is often at the call site, where Swift may report Missing argument label or Extraneous argument label.
9. Practical Mini Project
Let’s build a small notification helper that uses both argument labels and default values. This is a realistic example because notifications often need a required message plus a few optional settings.
func sendNotification(to user: String, message: String, priority: String = "normal", shouldLog: Bool = true) {
let finalMessage = "[\(priority.uppercased())] To \(user): \(message)"
print(finalMessage)
if shouldLog {
print("Notification logged.")
}
}
sendNotification(to: "Ava", message: "Your order has shipped.")
sendNotification(to: "Noah", message: "Server restart at 9 PM.", priority: "high")
sendNotification(to: "Mia", message: "Draft saved.", shouldLog: false)This function uses:
- to as a readable argument label
- user as the local parameter name inside the function
- two default values for common behavior
- explicit overrides only when needed
The result is an API that is short for normal use and still flexible for special cases.
10. Key Points
- Argument labels are the names used when calling a function.
- Parameter names are the local names used inside the function body.
- You can omit a label at the call site by using _ in the function declaration.
- Default values let callers leave out arguments when a standard value makes sense.
- A default value does not make a parameter optional.
- Labels are especially useful when parameters have similar types or roles.
- Good labels make function calls read clearly and reduce mistakes.
- Too many unlabeled parameters or poorly chosen defaults can make APIs harder to understand.
11. Practice Exercise
Create a function named scheduleMeeting with these rules:
- The first parameter should use the argument label with and local name person.
- The second parameter should be at with type String.
- The third parameter should be duration with type Int and a default value of 30.
- The function should print a sentence describing the meeting.
- Call the function once using the default duration and once with a custom duration.
Expected output: Two printed lines describing meetings, one with a 30-minute duration and one with your custom duration.
Hint: Use one external name and one local name for the first parameter, and remember that the default value belongs in the function declaration.
func scheduleMeeting(with person: String, at: String, duration: Int = 30) {
print("Meeting with \(person) at \(at) for \(duration) minutes.")
}
scheduleMeeting(with: "Taylor", at: "10:00 AM")
scheduleMeeting(with: "Chris", at: "2:00 PM", duration: 45)12. Final Summary
Swift argument labels and default values are small features with a big effect on code quality. Argument labels make function calls easier to read by describing what each value means, while default values reduce repetition by allowing common arguments to be omitted.
You also saw an important distinction: the label used in a function call is not always the same as the local parameter name inside the function, and a default value does not turn a parameter into an optional. Those details explain many beginner errors such as missing labels, extraneous labels, and confusion about parameter types.
As a next step, practice writing your own utility functions and focus on how they read at the call site. After that, a useful follow-up topic is Swift function overloading and parameter naming, because it builds directly on the design ideas you learned here.