Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Appendix A: Reference Summary

A condensed reminder of the syntax, in the order the book introduced it. It is for looking something up, not for learning it.

Declarations

let name = value                  // constant
var name = value                  // variable
let name: Type = value            // with the type written out
typealias Name = Type             // a second name for a type

Names are lowerCamelCase for values and functions, UpperCamelCase for types. A keyword may be used as a name by wrapping it in backticks.

Types

Int and the sized Int8 … Int64, UInt8 … UInt64. Double, Float. Bool. Character, String. [Element], [Key: Value], Set<Element>. (A, B) tuple, (A) -> B function, T? optional.

Conversion is an initializer: Double(n), Int(x) truncating, Int(exactly: x) returning nil when it will not fit, UInt8(truncatingIfNeeded: n) keeping the low bits.

Literals: 1_000_000, 0xff, 0o17, 0b1010, 1.6e-19, 0x1p-3.

Operators

Arithmetic + - * / %, wrapping &+ &- &*. Comparison == != < <= > >=, identity ===. Logical && || !, short-circuiting. Nil-coalescing ??. Conditional c ? a : b. Ranges a..<b, a...b, a..., ...b. Assignment produces no value.

Control Flow

if condition { } else if condition { } else { }
let x = if c { a } else { b }          // as an expression

guard condition else { return }        // else must leave
guard let x = optional else { return } // x stays in scope after

while condition { }
repeat { } while condition

for x in sequence { }
for x in sequence where condition { }
for (i, x) in sequence.enumerated() { }
for case .some(let x) in sequence { }

break, continue, break label, continue label
label: for ... { }
switch value {
case pattern:
case a, b:                    // alternatives
case 0..<10:                  // range
case let (x, y) where x > y:  // binding and filter
default:
}

Cases do not fall through; fallthrough if you want C’s behavior. A switch must be exhaustive, and no arm may be empty.

Functions and Closures

func name(label internal: Type = default, _ unlabeled: Type) -> Type { }
func name(_ items: Type...) -> Type { }          // variadic
func name(_ x: inout Type) { }                   // caller writes &x
func name() -> Never { }                         // does not return

A single-expression body needs no return. The full name includes the labels: name(label:_:).

{ (a: Type, b: Type) -> Type in body }
{ a, b in expression }
{ $0 < $1 }
f(x) { $0 < $1 }                 // trailing closure
{ [weak self, copied] in body }  // capture list
@escaping                        // parameter attribute, closure outlives the call

Optionals

var x: T?                       // Optional<T>
if let x { }                    // shorthand when the name is reused
if let y = x, let z = w, cond { }
guard let x else { }
while let x = f() { }
x ?? fallback
x?.member                       // whole chain is nil if any link is
x!                              // crash if nil
switch x { case .some(let v): ; case nil: }
x.map { }, x.flatMap { }

Types You Define

struct Name {
    let a: Int                  // stored
    var b: Int = 0
    var c: Int { a + b }        // computed, read-only
    var d: Int { get { } set { } }
    var e: Int = 0 { willSet { } didSet { } }
    static let shared = ...

    init(a: Int) { self.a = a }
    mutating func change() { }
}

final class Name: Super, Protocol {
    init() { super.init() }
    convenience init(x: Int) { self.init() }
    deinit { }
    override func method() { super.method() }
}

enum Name: RawType, CaseIterable {
    case simple
    case withValues(a: Int, b: String)
    indirect case recursive(Name)
}

protocol Name: AnyObject {
    var required: Int { get set }
    func method() -> Int
    init(x: Int)
    associatedtype Element
}

extension Existing: Protocol where Element: Comparable { }

weak var and unowned let do not raise the reference count; weak is optional and becomes nil.

Access, widest first: open, public, package, internal (the default), fileprivate, private. private(set) narrows only writing.

Generics

func f<T: Protocol>(_ x: T) -> T { }
func f<C: Collection>(_ x: C) -> C.Element? where C.Element: Comparable { }
struct Box<Element> { }
extension Box: Equatable where Element: Equatable { }

func f(_ x: some Protocol)      // one type, chosen by the caller
func f() -> some Protocol       // one type, hidden from the caller
let xs: [any Protocol]          // several types, boxed

Protocols the standard library uses: Equatable, Hashable, Comparable, CustomStringConvertible, Codable, Sequence, IteratorProtocol, Collection, Error, Sendable. Equatable, Hashable and Codable are synthesized when every stored property conforms.

Errors

enum MyError: Error { case bad(String) }

func f() throws -> Int { throw MyError.bad("why") }
func f() throws(MyError) -> Int { }        // typed throws
func f(_ body: () throws -> Void) rethrows { }

do {
    let x = try f()
} catch MyError.bad(let why) {
} catch let e as MyError {
} catch {                                   // binds `error`
}

try? f()        // -> Optional, nil on failure
try! f()        // crash on failure
defer { }       // runs on the way out, reverse order

Result<Success, Failure>, .success, .failure, get(), Result { try f() }

fatalError(), precondition(_:_:), assert(_:_:)

Concurrency

func f() async -> Int { }
let x = await f()

async let a = f()                    // starts now, awaited at first use
await withTaskGroup(of: T.self) { group in
    group.addTask { await f() }
    for await r in group { }
}
Task { }                             // unstructured; has cancel()
Task.isCancelled, try Task.checkCancellation()
try await Task.sleep(for: .milliseconds(100))

actor Name { }                       // one task inside at a time
@MainActor                           // the main-thread global actor
Sendable, @unchecked Sendable

Packages

// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "tool",
    targets: [
        .target(name: "Library"),
        .executableTarget(name: "tool", dependencies: ["Library"]),
        .testTarget(name: "LibraryTests", dependencies: ["Library"]),
    ],
    swiftLanguageModes: [.v6]
)

swift build, swift build -c release, swift run, swift test, swift package clean, swift-format.

Sources live in Sources/<target>; tests in Tests/<target>. A file named main.swift may hold top-level code; otherwise a type marked @main with static func main() is the entry point.

import Testing
@testable import Library

@Test func name() throws {
    #expect(a == b)
    let x = try #require(optional)
    #expect(throws: MyError.self) { try f() }
}