Lexical Structure and Style
|
This section documents the Swift 6 language mode as shipped by Swift 6.3, as published in The Swift Programming Language at docs.swift.org, which is the reference these pages are written and verified against. 6.4-beta-only features are always flagged as such — never presented as baseline. This content was generated with the assistance of AI and should be verified against docs.swift.org before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
This page covers the mechanics that apply to every other page in this section: how the compiler reads your text, how names and literals are written, and the naming conventions the rest of Swift — and this section — follows.
Whitespace and Comments
Whitespace (spaces, tabs, newlines) separates tokens but is otherwise not significant — Swift has no significant indentation. A newline does end a statement when no semicolon is present (see Semicolons).
// A single-line comment, to the end of the line.
/* A block comment.
/* Block comments nest, unlike in C or Java. */
That nesting is what lets you comment out a region that already contains a block comment. */
/// A single-line documentation comment, in a lightweight Markdown dialect.
/// - Parameter name: The name to greet.
/// - Returns: A greeting string.
func greeting(for name: String) -> String {
"Hello, \(name)!"
}
/**
* A multi-line documentation comment. Either `///` repeated per line or a `/** */` block
* is recognised by DocC and by Quick Help in Xcode; this section uses `///` throughout.
*/
DocC (via swift package generate-documentation or Xcode’s Build Documentation) renders /////** */
comments — including their Markdown, callouts (- Note:, - Warning:) and symbol links ( Type/member ) — into browsable reference documentation.
Identifiers and Keywords
An identifier starts with a letter, _, or certain Unicode categories (including emoji), and continues with
those plus digits and combining marks. Swift is case-sensitive.
Swift has no separate "contextual keyword" list exposed to you the way some languages do; instead, any keyword can be used as an identifier by escaping it with backticks:
let `class` = "still usable as a name"
let `for` = 10
func `return`() -> Int { 42 }
This matters most for interop — a C or Objective-C API might use a name that happens to be a Swift keyword — and is rarely needed in ordinary code; prefer renaming over backticks where you have the choice.
Swift’s reserved keywords fall into a few groups:
| Category | Examples |
|---|---|
Declarations |
|
Statements |
|
Expressions and types |
|
Concurrency (Swift 5.5+) |
|
Pattern matching |
|
A large second set are keywords only in specific positions (declaration modifiers, argument-label position,
attributes) and remain valid identifiers everywhere else — get, set, willSet, didSet, some, any,
nonisolated, sending, override, mutating, final, lazy, weak, unowned, and more. This is why, for
example, a parameter can be named set without conflict.
Literals
// Integer literals: decimal, binary, octal, hexadecimal; `_` as a free digit separator.
let decimal = 17
let readable = 1_000_000
let binary = 0b1010_0101
let octal = 0o21
let hex = 0x11
// Floating-point literals: decimal and hexadecimal (with a required binary exponent `p`).
let pi = 3.14159
let expo = 1.25e4 // 12500.0
let hexFloat = 0x1p2 // 4.0 (1 * 2^2)
// String literals.
let plain = "escapes: \n \t \\ \"; interpolation: \(1 + 1)"
let multiline = """
Preserves newlines.
Leading whitespace up to the closing quotes' indentation is stripped.
"""
let raw = #"No \escapes or \(interpolation) happen in here."#
let rawInterp = #"Unless you double the pound: \#(1 + 1)."#
// Regular expression literals (Swift 5.7+).
let regex = /[a-z]+\d+/
let anchored = #/^\d{3}-\d{4}$/# // extended delimiters allow `/` and whitespace inside the pattern
// Boolean and nil.
let flag: Bool = true
let absent: Int? = nil
A regex literal is checked for syntax at compile time and has static type Regex<Output>, inferred from its
capture groups — see Regular Expressions.
Operators
Operators are built from a fixed set of ASCII and Unicode "operator characters"
( / = - + ! * % < > & | ^ ~ ? plus a range of Unicode math/symbol code points); an operator token is a
maximal run of such characters, tokenised the same way regardless of which operator it turns out to be.
Whitespace around an operator controls whether it is parsed as infix, prefix or postfix:
let a = -1 // prefix `-`: no space after it, so it binds to `1`
let b = 3 - 1 // infix `-`: space on both sides
// let c = 3 -1 // error: ambiguous -- looks like `3` followed by a prefix `-1`
Swift lets you declare entirely new operators and custom precedence groups:
infix operator **: MultiplicationPrecedence
func ** (base: Double, exponent: Double) -> Double {
pow(base, exponent)
}
2.0 ** 10.0 // 1024.0
Semicolons
let x = 1
let y = 2 // no semicolon needed -- the newline ends the statement
let m = 1; let n = 2 // a semicolon is required only to put two statements on one line
A trailing semicolon after the last statement on a line is legal but never required, and is omitted throughout this section.
The API Design Guidelines
Swift’s standard library and virtually all published packages follow the API Design Guidelines, referenced directly from the language’s own documentation. The overriding goal is clarity at the point of use — a call site should read as a grammatical phrase, even at the cost of a longer declaration:
// Clear at the call site, even though the declaration repeats information:
extension Array {
func removingDuplicates() -> [Element] where Element: Hashable { /* ... */ Array(Set(self)) }
}
let unique = [1, 1, 2, 3].removingDuplicates()
// Argument labels form part of that phrase, distinct from the internal parameter name:
func move(_ piece: Piece, to destination: Square) { /* first arg unlabeled, second reads "to destination" */ }
move(knight, to: .e4)
Key rules the guidelines spell out:
-
Omit needless words — name a method
remove(at:), notremoveElement(atIndex:), when the type already makes the meaning obvious. -
Argument labels — the first argument is often unlabeled when the base reads naturally with it (
x.distance(to: y)), and every other argument is normally labeled; use_to suppress a label deliberately. -
Mutating/non-mutating pairs use
-ed/-ingfor the non-mutating, value-returning form and the bare verb for the mutating one:array.sort()mutates in place,array.sorted()returns a new array;set.formUnion(other)mutates,set.union(other)returns a new set. -
Fluent usage — read a call site as English where possible:
x.insert(y, at: z), notx.insert(y, z). -
Types and protocols are
UpperCamelCase; everything else (functions, methods, properties, cases, variables) islowerCamelCase.
MARK and TODO
// MARK: - Networking
// MARK: Equatable
// TODO: Replace with async/await once the minimum deployment target allows it.
// FIXME: This retries indefinitely on a 429 response.
// MARK: - (with a leading dash) inserts a separator line in Xcode’s jump bar/minimap in addition to a
section label; plain // MARK: adds a label without the separator. TODO/FIXME are recognised the same way
and surfaced in Xcode’s issue navigator, but carry no compiler meaning.
swift-format
swift-format (part of the swiftlang project, bundled with recent toolchains as swift format) is the
canonical formatter and linter, enforcing most of the layout conventions implied above — two-space
indentation, trailing-comma rules, brace placement — as well as a subset of the API Design Guidelines as lint
rules:
swift format lint --recursive Sources/ # report style violations
swift format format --recursive --in-place Sources/ # rewrite files in place
A .swift-format JSON file at the repository root configures indentation width, line length and which rules are
enabled, and is picked up automatically by both the CLI and Xcode’s built-in formatting support.
See Also
-
Getting Started — toolchains and the REPL/
swiftcworkflow that runs the examples above. -
Strings and Characters — string literals, interpolation and raw strings in depth.
-
Regular Expressions — the regex literal type and
RegexBuilder.