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() }
}