---
title: 'The Swift Language'
source: 'https://academia.sh/en/courses/swift'
language: en
updated: '2026-10-21T05:03:11+00:00'
license: 'CC BY-SA 4.0'
lessons: 24
outcomes:
    - "Uses Swift's type system and optional model correctly"
    - 'Explains the difference between value and reference semantics'
    - 'Builds extensible designs with protocols and extensions'
    - 'Distinguishes whether an expression is evaluated immediately, on first use, on every use, or never'
    - 'Recognizes the limits that automatic reference counting and strict concurrency checking place on code'
---

# The Swift Language

In Swift, the line where an expression is written and the moment it is evaluated are not always the same: a constant set up with let is ready once the line is passed, a property written with lazy waits until it is first read, a computed property runs again on every read, and the expression to the right of the && operator may never run. The course measures every mechanism with a single question — when is this expression evaluated? Constants, basic types, operators, functions and closures, optionals, structures and classes, protocols, generics, error handling, automatic reference counting, property wrappers, result builders and concurrency safety all pass through the same frame.

## Language Basics

Swift's design goals, constants and variables, type inference, basic types, the string and character model, operators, control flow with pattern-matching switch, functions with argument labels, and closures with capture lists.

### Swift's Design Goals

Source: https://academia.sh/en/courses/swift/design-goals-of-swift

Ties Swift's three goals — safety, expressiveness, performance — to one measurement axis: when is this expression evaluated? Splits eight expressions into four moments.

In earlier courses you asked what a program does. This course asks something else: when you write an expression, at which moment of the program does it run? You saw the split between compile time and run time in an earlier course (M11/K01); here we measure the order inside the run. Swift is the language of the iOS curriculum, and it is customary to introduce it through three goals.

#### Three Goals

Safety: the language tries to catch errors before the run. A constant cannot be read before it is assigned, and a value cannot be `nil` unless its type is an optional. In both cases the compiler rejects the program. These snippets do not compile in Swift 6.4; the compiler rejects both, which is why they have no output.

```swift
let total: Int
print(total)
```

```swift
var name: String = nil
```

Expressiveness: you do not have to write the type, because the compiler infers it from the right-hand side (type inference). The performance goal is not measured in this lesson; we do not measure time, only order.

#### The Measurement Axis: Four Moments

Throughout the course we ask a single question: when is this expression evaluated? There are four answers: **immediately**, **on first use**, **on every use** and **never**. The measurement harness has two parts. First comes the helper file; it stays the same through the whole lesson and always stands here as the first Swift block.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

`eval` wraps the expression and counts that it was evaluated; `use` wraps the access to the expression. The rule is simple: if it was never evaluated, `never`; if it was evaluated more than once, `on-every-use`; if it was evaluated once and that happened before the first use, `immediately`; otherwise `on-first-use`.

**LB1.** Every observation except `never` carries at least two uses; with a single use, one evaluation cannot tell `immediately` and `on-first-use` apart.

Eight expressions, eight `Probe` objects. A constant, a lazy property, a computed property, a function, a short circuit and a closure sit side by side in the same file; the course will split them into separate lessons one by one.

```swift
// main.swift — eight expressions, four moments
final class Basket {
    let lazyProbe: Probe
    let computedProbe: Probe
    var items = [3, 4, 5]

    init(lazyProbe: Probe, computedProbe: Probe) {
        self.lazyProbe = lazyProbe
        self.computedProbe = computedProbe
    }

    lazy var total: Int = lazyProbe.eval(items.reduce(0, +))
    var count: Int { computedProbe.eval(items.count) }
}

func square(_ x: Int, probe: Probe) -> Int { probe.eval(x * x) }

let constant = Probe("let-constant")
let lazyTotal = Probe("lazy-property")
let computed = Probe("computed-property")
let fallback = Probe("nil-coalescing-rhs")
let call = Probe("function-body")
let shortCircuit = Probe("and-operator-rhs")
let captured = Probe("capture-list")
let body = Probe("closure-body")

let limit = constant.eval(10)
_ = constant.use { limit }
_ = constant.use { limit }

let basket = Basket(lazyProbe: lazyTotal, computedProbe: computed)
_ = lazyTotal.use { basket.total }
_ = lazyTotal.use { basket.total }
_ = computed.use { basket.count }
_ = computed.use { basket.count }

let stored: Int? = 7
_ = fallback.use { stored ?? fallback.eval(0) }
_ = fallback.use { stored ?? fallback.eval(0) }

_ = call.use { square(3, probe: call) }
_ = call.use { square(4, probe: call) }

let ready = false
_ = shortCircuit.use { ready && shortCircuit.eval(true) }
_ = shortCircuit.use { ready && shortCircuit.eval(true) }

let step = 2
let addStep = { [step = captured.eval(step)] (x: Int) -> Int in x + step }
_ = captured.use { addStep(1) }
_ = captured.use { addStep(2) }

let double = { (x: Int) -> Int in body.eval(x * 2) }
_ = body.use { double(3) }
_ = body.use { double(4) }

let probes = [constant, lazyTotal, computed, fallback, call, shortCircuit, captured, body]
for probe in probes { probe.report() }
tally(probes)
```

```
let-constant: 1 evaluations, 2 uses -> immediately
lazy-property: 1 evaluations, 2 uses -> on-first-use
computed-property: 2 evaluations, 2 uses -> on-every-use
nil-coalescing-rhs: 0 evaluations, 2 uses -> never
function-body: 2 evaluations, 2 uses -> on-every-use
and-operator-rhs: 0 evaluations, 2 uses -> never
capture-list: 1 evaluations, 2 uses -> immediately
closure-body: 2 evaluations, 2 uses -> on-every-use
immediately: 2
on-first-use: 1
on-every-use: 3
never: 2
```

The eight expressions split into four moments: two `immediately`, one `on-first-use`, three `on-every-use`, two `never`. This count is the course's binding tally; the later lessons open each expression in its own lesson. A `let` constant is evaluated on the line where it is defined. A `lazy` property is built when it is first read and then stored, while a computed property is calculated again on every read. A function body runs on every call; the right side of the `??` operator never runs because the left side is filled, and the right side of the `&&` operator never runs because the left side is false. A capture list is evaluated once, when the closure is created; the closure's body is evaluated on every call.

**LB2.** The constant and the capture list land on the same moment, but by different paths; this lesson measures only the moment, not the mechanism.

#### A Value Copy Does Not Recompute

One leg of Swift's safety goal is value semantics: value types such as arrays, strings and structures are copied on assignment, and the copy is an independent value. When you assign one variable to another, changing either one does not affect the other. This property comes from the design concern that no state should be shared by accident. The measurement question is a different one: does the copy re-evaluate the expression that produced the source, or does it merely duplicate the existing value?

The block below produces an array with a `Probe`, copies it into a second variable named `duplicate`, and changes the two arrays independently. It then reads both variables; the reads count as two uses.

```swift
// Copy.swift — a copy does not run the expression again
let sourceProbe = Probe("source-array")
var original = sourceProbe.eval([1, 2, 3])
var duplicate = original
duplicate.append(4)
original.append(9)
_ = sourceProbe.use { original.count }
_ = sourceProbe.use { duplicate.count }
print(original, duplicate)
sourceProbe.report()
```

```
[1, 2, 3, 9] [1, 2, 3, 4]
source-array: 1 evaluations, 2 uses -> immediately
```

The 9 appended to `original` did not show up in `duplicate`, and the 4 appended to `duplicate` is not in `original`. The two variables separated at the moment of assignment and each went its own way. The measurement line says the expression was evaluated only once: assignment duplicates a value, it does not run the expression that produced it again. Because the evaluation happens in the `var` definition, before the two reads, the moment comes out as `immediately`.

This distinction makes the safety goal concrete. If assignment recomputed the source, every copy could produce its result at a different moment; in the measured behavior, a copy is a snapshot of the value at the moment of assignment. Later changes apply to each side separately.

**LB3.** The independence of the copy was measured with an array of `Int`; sharing of elements in the copy of an array that holds class instances is not the subject of this lesson.

#### A Constant Binding Does Not Freeze the Object

Another end of the safety goal concerns `let`, and it is often misread. When you bind a class instance with `let`, what is bound is the reference to the instance. Writing a constant instead of a variable stops the name `holder` from pointing at another object, but it does not lock the object's own `var` properties. You can read the same rule the other way round for value types: if you bind a structure with `let`, you cannot change its properties either; a class has no such ban.

The block below defines a small class, binds it with `let`, and still changes the counter inside it with two assignments. The counter value comes through a `Probe`; two separate assignments bring two separate evaluations.

```swift
// Holder.swift — let does not freeze the object
final class Holder {
    var count = 0
}
let holderProbe = Probe("class-counter")
let anchor = Holder()
_ = holderProbe.use { anchor.count = holderProbe.eval(5) }
_ = holderProbe.use { anchor.count = holderProbe.eval(8) }
print(anchor.count)
holderProbe.report()
```

```
8
class-counter: 2 evaluations, 2 uses -> on-every-use
```

Although `anchor` is a `let` constant, `anchor.count` was assigned twice and the final value, 8, was read. What is constant is the reference that the name `anchor` is bound to; the inside of the object is variable. The measurement line shows two evaluations, because the two assignments made two separate `eval` calls: the `let` rule does not restrict the number of assignments here, since what is assigned is not `anchor` but the `anchor.count` field. That is why the moment is `on-every-use`.

The design takeaway is this: `let` guarantees that a binding cannot be made again; it does not guarantee that the object is immutable. If you want immutability, make the fields `let` as well, or use a value type.

**LB4.** The class instance was measured with a single field; the claim that the same assignment does not compile on a value type bound with `let` lies outside this lesson, as source-level knowledge.

#### Type Inference Does Not Change the Moment

The most visible part of the expressiveness goal is type inference: if you write `let size = 12`, the compiler finds the `Int` type itself and you do not have to write it. If you like, you can also write the type explicitly: `let size: Int = 12`. The question that comes to mind is whether inference has a run-time cost or a timing. Type inference finishes at compile time; the running program does not know how the type was found.

The block below defines the same value in two ways: one by inference, one with an explicit type annotation. Each is tied to its own `Probe` and read twice; the types of both variables are printed with `type(of:)`.

```swift
// Inference.swift — inference and an explicit type give the same moment
let inferredProbe = Probe("inferred-type")
let declaredProbe = Probe("explicit-type")
let inferred = inferredProbe.eval(42)
let declared: Int = declaredProbe.eval(42)
_ = inferredProbe.use { inferred + 1 }
_ = inferredProbe.use { inferred + 2 }
_ = declaredProbe.use { declared + 1 }
_ = declaredProbe.use { declared + 2 }
print(type(of: inferred), type(of: declared))
inferredProbe.report()
declaredProbe.report()
```

```
Int Int
inferred-type: 1 evaluations, 2 uses -> immediately
explicit-type: 1 evaluations, 2 uses -> immediately
```

The two variables print the same type, and the two `Probe` objects gave the same moment: both are one evaluation, two uses, `immediately`. The explicit type annotation did not move the expression to another time; it only told the compiler what to find. This is why the course's measurement axis is insensitive to type inference: what determines when an expression is evaluated is not whether the type is written, but the context in which the expression stands.

**LB5.** Type inference was measured in this lesson only with an `Int` literal; the claim that inference leaves timing untouched for other literals and kinds of expression lies outside this lesson.

#### A Lazy Transformation Waits Until It Is Called

The expressiveness goal of the design also raises the question of when something written briefly actually runs. When you call `map` on an array, the transformation is done immediately, for every element. If you call `map` on the `lazy` view of the same array, the transformation runs for no element at the moment it is defined; it runs only when an element is requested, and only for that element. This is not the array counterpart of the `lazy var` property we saw earlier, but it carries the same intuition: work can be deferred until someone asks for the result.

The block below sets up two `Probe` objects. The body of the eager transformation records evaluations on `eagerProbe`, and the body of the lazy transformation records them on `lazyProbe`. The counters are printed right after the transformations and again after two elements are pulled from the lazy view. The `evaluations` property is a readable counter inside `Probe`.

```swift
// LazyMap.swift — eager and lazy transformation
let eagerProbe = Probe("eager-transform")
let lazyMapProbe = Probe("lazy-transform")
let values = [1, 2, 3]
let eagerDoubled = values.map { eagerProbe.eval($0 * 2) }
let lazyDoubled = values.lazy.map { lazyMapProbe.eval($0 * 2) }
print(eagerProbe.evaluations, lazyMapProbe.evaluations)
_ = lazyMapProbe.use { Array(lazyDoubled.prefix(2)) }
print(eagerProbe.evaluations, lazyMapProbe.evaluations)
_ = lazyMapProbe.use { Array(lazyDoubled.prefix(2)) }
print(eagerDoubled, Array(lazyDoubled.prefix(1)))
lazyMapProbe.report()
```

```
3 0
3 2
[2, 4, 6] [2]
lazy-transform: 5 evaluations, 2 uses -> on-every-use
```

The first line came out as `3 0`: the eager `map` transformed all three elements immediately, while the lazy `map` had not yet touched any. On the second line the lazy counter became 2, because `prefix(2)` asked for the transformation of only two elements; the third element was never computed. When the same `prefix(2)` was called a second time, the transformation ran again, because a lazy view does not store its results; the five evaluations on the last `report` line show this: two, two, and one from the final `prefix(1)` call.

The expressiveness goal leaves it to you to tell these two behaviors apart. The eager `map` produces the result once and stores it. The lazy view keeps the writing short, but it may redo the work on every pull. Which is right depends on how many times the result will be read and whether the body has a side effect.

**LB6.** The lazy transformation was measured only for elements pulled with `prefix`; how the `lazy` view changes the count under `filter` or chained transformations lies outside this lesson.

#### The Bounding Measurement

The rule counts, it does not read intent. If you write the same `let` expression as two separate constants with two separate `Probe` objects, both come out `immediately`. If you tie the same expression to a single `Probe`, the second `eval` raises the count to two and the rule says `on-every-use`; the intent of the code has not changed, but the measurement harness has.

```swift
// Twin.swift — the same expression, two probes and one probe
let first = Probe("first-constant")
let second = Probe("second-constant")
let shared = Probe("shared-constant")

let a = first.eval(5)
let b = second.eval(5)
let c = shared.eval(5)
let d = shared.eval(5)

for probe in [first, second, shared] {
    _ = probe.use { a + b + c + d }
    _ = probe.use { a + b + c + d }
    probe.report()
}
```

```
first-constant: 1 evaluations, 2 uses -> immediately
second-constant: 1 evaluations, 2 uses -> immediately
shared-constant: 2 evaluations, 2 uses -> on-every-use
```

**LB7.** This measurement reads the number of `eval` calls, not how the expression is written; we do not count `Probe` as a language feature.

#### Summary

- Swift provides safety through the compiler: an unassigned constant cannot be read, and a non-optional value cannot be `nil`.
- Expressiveness is type inference; the performance goal is not measured in this lesson.
- The course's measurement axis: when is this expression evaluated? Four moments: immediately, on first use, on every use, never.
- The `Probe` rule reads the count; it does not read intent.
- This lesson's moment: **immediately** (a `let` constant, on the line where it is defined).

#### Next Step

A constant is evaluated the moment it is defined; but what happens when a `var` is reassigned, and can a constant be assigned after it has been defined? The next lesson measures the assignment moments of constants and variables.

### Constants and Variables

Source: https://academia.sh/en/courses/swift/constants-and-variables

Measures `let` and `var` together with type inference, explicit type annotation and the moment of assignment: is a constant evaluated immediately, and is an assignment evaluated every time?

In the previous lesson you saw that a `let` constant is evaluated **immediately**, on the line where it is defined. This lesson pushes that observation from three directions: does writing a type on a constant change anything, what does `var` do on each assignment, and does the moment shift if the value is assigned after the definition? You know variables and types from the Programming Fundamentals course (M01/K02); here we measure only what is specific to Swift.

#### Constants, Variables and Types

In Swift, `let` defines a constant that is bound once, and `var` defines a variable that can change later. You usually do not write the type: the compiler infers it from the right-hand side (type inference). If you like, you write the type after a colon (explicit type annotation). A second assignment to a constant is rejected by the compiler: the snippet below does not compile in Swift 6.4, which is why it has no output.

```swift
let rate = 4
rate = 5
```

The same assignment is allowed for `var`. The difference is not only in the syntax: a `var` line evaluates its right-hand side again on every assignment.

#### Three Forms of Assignment

First the `Probe.swift` helper file; it stays the same in every lesson.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

Now three `Probe` objects: one tracks a constant whose type is inferred, one a constant whose definition and assignment are separated, and one a variable that is assigned three times.

```swift
// main.swift — assignment moments of a constant and a variable
let inferredProbe = Probe("inferred-constant")
let deferredProbe = Probe("deferred-constant")
let counterProbe = Probe("variable-assignment")

let rate = inferredProbe.eval(4)
let explicitRate: Double = 4
_ = inferredProbe.use { rate }
_ = inferredProbe.use { rate }
print("\(type(of: rate)) \(type(of: explicitRate))")

let isWeekend = false
let level: Int
if isWeekend {
    level = deferredProbe.eval(1)
} else {
    level = deferredProbe.eval(2)
}
_ = deferredProbe.use { level }
_ = deferredProbe.use { level }

var total = counterProbe.eval(0)
total = counterProbe.eval(total + 5)
total = counterProbe.eval(total + 7)
_ = counterProbe.use { total }
_ = counterProbe.use { total }

let allProbes = [inferredProbe, deferredProbe, counterProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
Int Double
inferred-constant: 1 evaluations, 2 uses -> immediately
deferred-constant: 1 evaluations, 2 uses -> immediately
variable-assignment: 3 evaluations, 2 uses -> on-every-use
immediately: 2
on-first-use: 0
on-every-use: 1
never: 0
```

The first line shows the types: the `4` written without a type is an `Int`, and the same number declared as `Double` is a `Double`. Type inference did not change the evaluation moment; the inferred constant was evaluated on the line where it is defined, before the first use, so it is `immediately`.

`level` is the interesting case: an `if` sits between the definition (`let level: Int`) and the value, but the assignment still happened before any use. Both branches call `eval`, but only one of them runs; the count is one, and the moment is again `immediately`. The compiler rejects a read before the assignment (the first snippet of the previous lesson), so no read can sit between the definition and the assignment; but if the assignment is made inside a wrapper around a use, the measurement gives `on-first-use` (see the Deferred Initial Value section below).

`var` is different. `total` was assigned three times, and each assignment evaluated its right-hand side again; the rule reads this as `on-every-use`. A variable is not a constant bound once; every assignment is a new evaluation.

**LB8.** The assignments to `counterProbe` happen before the uses, but because there are three evaluations the rule says `on-every-use`; when the count is more than one, "before or after" is not examined.

**LB9.** The `type(of:)` output prints only the names `Int` and `Double`; a type name points at the result of inference, not at the measurement axis.

#### Type Inference and Explicit Type Annotation

When you define a constant or a variable, you do not have to write the type. On the line `let attempts = 3`, the compiler infers `Int` from the literal on the right; this is called type inference. If you like, you write the type explicitly after a colon: `let ratio: Double = 3`. This is called explicit type annotation. The only difference between the two is who decides the type: with inference the type comes from the value, with an explicit annotation the form of the value comes from the type.

The difference shows most when you write a literal number. The literal `3` becomes an `Int` under inference, but if you write `Double` on the left, the same literal is read as `3.0`. The block below binds the same literal `3` in two ways, passes each through a `Probe` and reads each twice.

```swift
// Literal.swift — the same literal, two types
let inferredProbe = Probe("inferred-int")
let declaredProbe = Probe("explicit-double")
let attempts = inferredProbe.eval(3)
let ratio: Double = declaredProbe.eval(3)
_ = inferredProbe.use { attempts }
_ = inferredProbe.use { attempts }
_ = declaredProbe.use { ratio }
_ = declaredProbe.use { ratio }
print(attempts, ratio)
print(type(of: attempts), type(of: ratio))
inferredProbe.report()
declaredProbe.report()
```

```
3 3.0
Int Double
inferred-int: 1 evaluations, 2 uses -> immediately
explicit-double: 1 evaluations, 2 uses -> immediately
```

`attempts` was printed as `3` and `ratio` as `3.0`; the `type(of:)` line confirms that the types are `Int` and `Double`. The literal was written the same way, but the type coming from the context turned it into two different values. The two `Probe` objects gave the same moment: both are `immediately`. The type determines only what the value is, not when it is evaluated. The compiler finds the type without running the code; all that remains at run time is a single `eval` call.

So an explicit type annotation does two jobs. The first is to ask for a type different from the one inference would choose. The second is to show the reader the intent behind the value. On the measurement axis, the two are equal.

**LB10.** Inference and annotation were measured with the same literal `3`; how early the type is found in a more complex expression lies outside this lesson.

#### Tuple Decomposition and Several Definitions on One Line

Swift lets you define more than one name on a single constant or variable line. You can write `var left = 0, right = 0` separated by a comma; each name is bound to its own expression separately. Another way is to take a tuple apart: `let (low, high) = (1, 9)` defines two constants and distributes the elements of the tuple to them in order. This syntax is known as tuple decomposition.

The question that comes to mind is this: when two names are defined on the same line, are their expressions evaluated at the same moment, or does one come before the other? The block below defines two names from a tuple with two separate `Probe` objects, then defines two `var` names on a single line and assigns them in turn.

```swift
// Decompose.swift — tuple decomposition and several definitions on one line
let lowProbe = Probe("lower-bound")
let highProbe = Probe("upper-bound")
let (low, high) = (lowProbe.eval(1), highProbe.eval(9))
_ = lowProbe.use { low }
_ = lowProbe.use { low + 1 }
_ = highProbe.use { high }
_ = highProbe.use { high - 1 }
var left = 0, right = 0
left = lowProbe.eval(low)
right = highProbe.eval(high)
_ = lowProbe.use { left }
_ = highProbe.use { right }
print(low, high, left, right)
lowProbe.report()
highProbe.report()
```

```
1 9 1 9
lower-bound: 2 evaluations, 3 uses -> on-every-use
upper-bound: 2 evaluations, 3 uses -> on-every-use
```

Both elements of the tuple were evaluated on the definition line, before any read. But that was not the only evaluation: `lowProbe` and `highProbe` each showed one evaluation, and then the assignments to `left` and `right` added a second one each. That is why both measurement lines gave two evaluations, three uses and `on-every-use`. A definition on one line or a tuple decomposition does not merge the expressions into a single step; each element is evaluated as many times as its own expression.

The principle here is this: how many times an expression is evaluated is decided not by how many lines you write it on, but by how many evaluation points like `eval` there are. Tuple decomposition shortens the writing; it does not change the order at run time.

**LB11.** Tuple decomposition was measured with two elements and constant literals; the order in which nested tuples are taken apart lies outside this lesson.

#### Shadowing

In an inner scope you can redefine the same name as in an outer scope. This is called shadowing: the name in the inner scope hides the one in the outer scope until the scope ends. The outer variable or constant does not change in any way; only the reads in the inner scope go to the new name. This behavior is the safe way to transform a value temporarily and keep using the same name.

Shadowing is not a new assignment. When `amount` is defined a second time with `let`, the outer `amount` stays as it is; the new definition is a second evaluation, and it lives only in its own scope. The block below shadows the outer constant `amount` inside a `do` scope, prints the inner value, leaves the scope and prints the outer value again.

```swift
// Shadow.swift — shadowing does not change the outer value
let outerProbe = Probe("outer-scope")
let innerProbe = Probe("inner-scope")
let amount = outerProbe.eval(1)
do {
    let amount = innerProbe.eval(amount + 10)
    _ = innerProbe.use { amount }
    _ = innerProbe.use { amount * 2 }
    print(amount)
}
_ = outerProbe.use { amount }
_ = outerProbe.use { amount + 5 }
print(amount)
outerProbe.report()
innerProbe.report()
```

```
11
1
outer-scope: 1 evaluations, 2 uses -> immediately
inner-scope: 1 evaluations, 2 uses -> immediately
```

Inside the inner scope `amount` printed 11: the `amount` on the right side of the inner definition was still the outer constant, because the inner name had not been bound yet. After leaving the scope, `amount` was 1 again; shadowing never changed the outer constant. The two `Probe` objects each showed one evaluation and two uses: both are `immediately`. Shadowing adds a new evaluation, but because it is not a reassignment, it does not raise the count on the outer side.

In practice, shadowing is a tidy way to transform a value without multiplying variable names. In return, the reader has to know which `amount` they are looking at; keeping the scope short reduces that burden.

**LB12.** Shadowing was measured with a `do` scope; the behavior of shadowing a function parameter or a loop variable lies outside this lesson.

#### Deferred Initial Value

You do not have to give a `let` constant its value on the line where it is defined. You can write the type and assign the value later, as long as the compiler can see that the constant receives a value exactly once on every path. This rule keeps the "unchangeable" meaning of the `let` declaration: a constant cannot be read until it receives its first value, and it cannot be reassigned after that. In a branching flow, each branch fills the constant once, and the constant is ready at the end of the branch.

This has an effect that can be measured: only the expression of the chosen branch runs. The block below writes a function. In the function, the constant `label` is declared first, then filled with a value from the `Probe` in one branch and with a fixed string in the other branch through an `if`. The function is called first with `true`, then with `false`.

```swift
// Deferred.swift — deferred initial value
func pick(open: Bool, probe: Probe) -> String {
    let label: String
    if open {
        label = probe.eval("open")
    } else {
        label = "closed"
    }
    return label
}
let pickProbe = Probe("deferred-constant")
print(pickProbe.use { pick(open: true, probe: pickProbe) })
print(pickProbe.use { pick(open: false, probe: pickProbe) })
pickProbe.report()
```

```
open
closed
deferred-constant: 1 evaluations, 2 uses -> on-first-use
```

The `true` call gave `open` and the `false` call gave `closed`. The compiler accepted this because a new `label` constant is defined on each call and each one is filled once. The `Probe` showed one evaluation for two uses: `probe.eval` ran only in the `true` branch, and the fixed string of the `false` branch never touched the `Probe`. An expression that is evaluated on first use and does not run again is the mark of the `on-first-use` moment; here the second call never reached that expression.

This behavior shows that deferred initial value is a rule: every path fills the constant exactly once, and a path that does not fill it computes nothing. The value of the constant comes from the expression of whichever branch the flow enters. If you forget the assignment in a branch, the compiler does not let you use the constant after that point.

The rule is also useful when you prepare the return value of a function: the constant is declared, the branches fill it, and a single `return` is left at the end of the function. Using `var` and changing it later would also work, but `let` tells the compiler and the reader that the value is assigned once.

**LB13.** Deferred initial value was measured with two branches and inside a function; the rules of the same structure in top-level code or in properties lie outside this lesson.

#### The Bounding Measurement

A constant being evaluated **immediately** does not hold everywhere. A global constant defined in another file is set up on first access. The helper file below puts a `print` in the initialization closure; the closure is inside the `let` definition.

```swift
// Config.swift — a global constant in another file
let appName: String = {
    print("setting up appName")
    return "academia"
}()
```

`main.swift` defines a local constant with the same pattern and shows, in line order, when the two constants are set up.

```swift
// main.swift — setup moment of a global and a local constant
print("start")
let localName: String = {
    print("setting up localName")
    return "academia"
}()
print("second line")
print("read: \(appName)")
print("local: \(localName)")
```

```
start
setting up localName
second line
setting up appName
read: academia
local: academia
```

`localName` was set up in the top level of `main.swift`, on the line where it is written (`immediately`); `appName` was set up after the second line, inside the `print` that read it first (`on-first-use`). The same way of writing has two different moments.

**LB14.** `Probe` cannot enter this observation: `Probe` is not `Sendable` and cannot be held as a global constant under the Swift 6 rules; so the moment here is read from the order of the `print` lines, not from a count.

**LB15.** This measurement covers only one global constant and only one helper file; we do not measure other cases of the ordering rule (for example, several global constants whose setup depends on each other).

#### Summary

- `let` is bound once, and a second assignment is rejected by the compiler; `var` can be reassigned.
- Type inference and explicit type annotation do not change the evaluation moment.
- Deferred initialization can be read only after the assignment; it gives `immediately` if the assignment comes before the use, and `on-first-use` if it is inside a wrapper around a use.
- Every `var` assignment evaluates its right-hand side again; the rule reads this as `on-every-use`.
- This lesson's moment is **immediately** (a constant evaluated on the line where it is defined or assigned).

#### Next Step

We measured the assignment moments of constants and variables. The next lesson looks at the types of the values placed in them: when is a conversion between `Int`, `Double`, `Bool` and `String` made?

### Basic Types

Source: https://academia.sh/en/courses/swift/basic-types

Introduces the `Int`, `Double`, `Bool` and `String` types; measures that conversion is explicit and that a conversion expression is evaluated immediately.

We saw the moment of assignment for a constant and a variable: on the line where it is defined, **immediately**. Now we look at the assigned value itself. Swift has four basic types: `Int` for integers, `Double` for floating-point numbers, `Bool` for logical values and `String` for text. This lesson asks one question: when is an expression that converts one type to another evaluated?

#### Conversion Is Explicit

Swift does not mix two types on its own. If you try to add an `Int` and a `Double`, the compiler rejects the program: the snippet below does not compile in Swift 6.4, which is why it has no output.

```swift
let count = 1
let size = 2.5
print(count + size)
```

The fix is to write the conversion: `Double(count)`. A conversion is an expression of its own, and if it is written inside a `let`, it is evaluated once, on that line. This lesson's measurement confirms it. First the helper file that stays the same in every lesson.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The measurement starts with two `Probe` objects: one tracks the conversion, and the other tracks a tuple element. Next to the conversion there are two floating-point observations and a print of `Int.max`, because why a `Double` comparison surprises is this lesson's subject. The helper function `marked` shows the order of the tuple elements with `print`. `unusedProbe` tracks a tuple element that is never read.

```swift
// main.swift — conversion and tuple moments
let conversionProbe = Probe("type-conversion")
let tupleProbe = Probe("tuple-element")
let unusedProbe = Probe("unused-element")

let wholeCount = 7
let ratio = conversionProbe.eval(Double(wholeCount) / 2)
_ = conversionProbe.use { ratio }
_ = conversionProbe.use { ratio }
print(ratio)
print(Int.max)
print(0.1 + 0.2 == 0.3)
print(0.1 + 0.2)

func marked(_ n: Int) -> Int { print("value \(n)"); return n }
let triple = (marked(1), marked(2), marked(3))
print(triple.1)

let record = (size: tupleProbe.eval(3), spare: unusedProbe.eval(9))
_ = tupleProbe.use { record.size }
_ = tupleProbe.use { record.size }

let allProbes = [conversionProbe, tupleProbe, unusedProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
3.5
9223372036854775807
false
0.30000000000000004
value 1
value 2
value 3
2
type-conversion: 1 evaluations, 2 uses -> immediately
tuple-element: 1 evaluations, 2 uses -> immediately
unused-element: 1 evaluations, 0 uses -> immediately
immediately: 3
on-first-use: 0
on-every-use: 0
never: 0
```

`ratio` gives seven divided by two as 3.5, because the division was done on `Double`. `Int.max` prints the largest `Int` value; one more than this value is a program error and was left out of the lesson's measurement. `0.1 + 0.2 == 0.3` gives `false`, against expectation: the addition does not produce exactly 0.3 but a number very close to it. Because a floating-point number cannot be represented exactly in base two, you measure a difference instead of testing equality; this is not a Swift feature but a consequence of the `Double` representation.

The conversion line was evaluated once, on the line where it is defined, before the first use: `type-conversion` came out `immediately` with two uses. The tuple elements were evaluated from left to right: `value 1`, `value 2`, `value 3`. A tuple is a structure that gathers several values into a single value; its elements are ready on the definition line.

**LB16.** The `Int.max` print is valid only for a 64-bit `Int`; the compiler used for the measurement compiled for a 64-bit target.

**LB17.** `0.1 + 0.2 == 0.3` was measured with two constant expressions; whether the evaluation that does the arithmetic happens in the compiler or at run time is not told apart in this lesson.

#### Numeric Type Initializers

Swift does not convert implicitly between different numeric types; you write the conversion. The tool for it is the type's initializer: `Double(7)`, `Int(3.9)`, `UInt8(200)`. The initializer that turns a fractional value into an `Int` drops the fractional part, that is, it truncates toward zero; `Int(3.9)` gives 3, and `Int(-3.9)` gives -3. If you need rounding, you write a separate operation.

To measure this behavior, the block below produces a fractional number through a `Probe` and passes it through two different initializers. The initializer is the expression itself; so the `eval` call that produces the number sits inside the argument of the initializer.

```swift
// Convert.swift — conversion with initializers
let truncateProbe = Probe("truncating-conversion")
let widenProbe = Probe("widening-conversion")
let cut = Int(truncateProbe.eval(3.9))
let negativeCut = Int(truncateProbe.eval(-3.9))
let wide = Double(widenProbe.eval(7))
let small = UInt8(widenProbe.eval(200))
_ = truncateProbe.use { cut + negativeCut }
_ = truncateProbe.use { cut - negativeCut }
_ = widenProbe.use { wide }
_ = widenProbe.use { small }
print(cut, negativeCut, wide, small)
truncateProbe.report()
widenProbe.report()
```

```
3 -3 7.0 200
truncating-conversion: 2 evaluations, 2 uses -> on-every-use
widening-conversion: 2 evaluations, 2 uses -> on-every-use
```

`Int(3.9)` gave 3 and `Int(-3.9)` gave -3; that is, the conversion truncates toward zero. `Double(7)` was printed as `7.0`, and `UInt8(200)` stayed 200. Both measurement lines showed two evaluations: each initializer call evaluated its argument once, and because each `Probe` is tied to two initializers, the count rose to two. That is why both lines read `on-every-use`; the count is the product of the measurement harness, not of the conversion.

What matters here is the place where an initializer can fail: a value like `UInt8(300)` does not fit this type, and the program stops. So when you write a conversion, you need to know in advance that the value fits the target type. The lesson does not run this case.

**LB18.** The conversions were measured only with values that fit the type; the case of a value that does not fit is not run in this lesson, only described.

#### Overflow Operators

Integer types have limits. A `UInt8` value stays between 0 and 255. If the regular `+` operator pushes the result past this limit, the program stops. Swift also offers operators that accept overflow: `&+`, `&-` and `&*`. These operators wrap the result around according to the type's capacity. The `&` prefix is the way to say that you want overflow on purpose; it does not happen silently, it happens by choosing the operator.

The block below adds a number to a `UInt8` value with `&+` inside a function. Because the added number comes through a `Probe`, each call counts as one evaluation. The first call adds 10 to 250 and passes the limit; the second call works with a safe value.

```swift
// Wrap.swift — the overflow operator wraps around
func bump(_ value: UInt8, probe: Probe) -> UInt8 {
    value &+ probe.eval(10)
}
let wrapProbe = Probe("overflow-operator")
print(wrapProbe.use { bump(250, probe: wrapProbe) })
print(wrapProbe.use { bump(1, probe: wrapProbe) })
let floor: UInt8 = 0
print(floor &- 1, UInt8.max)
wrapProbe.report()
```

```
4
11
255 255
overflow-operator: 2 evaluations, 2 uses -> on-every-use
```

`250 &+ 10` did not come out 260; the result was 4, because after 255 the count returned to 0. `1 &+ 10` gave the normal 11. On the third line, `0 &- 1` came out 255, the same as `UInt8.max`: the number that went below the limit wrapped around to the upper end. The measurement line shows two evaluations: each `bump` call evaluated its operand once, so the moment is `on-every-use`.

Overflow operators can be measured because the program does not stop. The same overflow with the regular `+` does stop it, and for that reason it is not run in this lesson. Which one you choose depends on your intent: write `&+` if you want wrapping, and `+` if you want overflow to be an error.

**LB19.** The overflow operator was measured with `UInt8`; the wrapping behavior of signed types with `&+` was not measured in this lesson.

#### Type Aliases and Limits

Every numeric type has a lower and an upper limit, and the type exposes them as the static properties `min` and `max`: `Int8.min` is -128, `Int8.max` is 127, `UInt8.max` is 255. Knowing a type's limit answers the overflow question on the spot. When you want to give a type another name in code, you use `typealias`: `typealias Pixel = UInt8`. An alias is not a new type; it is a second name for the same type and carries its limits and behavior unchanged.

The block below defines the `Pixel` alias, binds a constant with it, and prints the constant's type and limits. The constant comes from a `Probe` and is read twice.

```swift
// Alias.swift — a type alias is the same type
typealias Pixel = UInt8
let aliasProbe = Probe("alias-constant")
let brightness: Pixel = aliasProbe.eval(200)
_ = aliasProbe.use { brightness }
_ = aliasProbe.use { brightness &+ 100 }
print(type(of: brightness), Pixel.max, Int8.min)
aliasProbe.report()
```

```
UInt8 255 -128
alias-constant: 1 evaluations, 2 uses -> immediately
```

`type(of: brightness)` printed `UInt8`, so the alias did not create a new type. `Pixel.max` came out 255 and `Int8.min` came out -128. The `Probe` showed a single evaluation, and because the constant was set up before the use, the moment is `immediately`. An alias is only a convenience at the level of names; it adds nothing at run time.

Knowing the limit properties is the basis of conversion and overflow decisions. You can check ahead of time whether a value will fit by comparing it with `max`; that way you never run a conversion that does not fit.

**LB20.** The limit values were shown with `UInt8` and `Int8`; the limits of the other integer types lie outside this lesson.

#### Converting a Fraction to an Integer

There is not a single way to turn a `Double` value into an `Int`, and three common ways give different results. `Int(value)` drops the fractional part, that is, it truncates toward zero. `value.rounded()` rounds to the nearest whole value; on an exact midpoint it goes away from zero. `value.rounded(.down)` always goes down to the smaller one. The three either produce a `Double` first or give an `Int` directly; which way you choose changes the result for negative numbers.

The block below converts one number in three ways. The value to convert comes from a `Probe`, and the function is called with a positive and a negative value.

```swift
// Rounding.swift — converting a fraction to an integer
func convert(_ value: Double, probe: Probe) -> (Int, Int, Int) {
    let source = probe.eval(value)
    return (Int(source), Int(source.rounded()), Int(source.rounded(.down)))
}
let roundProbe = Probe("rounding")
print(roundProbe.use { convert(2.5, probe: roundProbe) })
print(roundProbe.use { convert(-2.5, probe: roundProbe) })
roundProbe.report()
```

```
(2, 3, 2)
(-2, -3, -3)
rounding: 2 evaluations, 2 uses -> on-every-use
```

For positive `2.5` the three ways gave `(2, 3, 2)`: truncation 2, rounding to nearest 3, rounding down 2. For negative `-2.5` the result was `(-2, -3, -3)`. Truncation moves toward zero, so it gave `-2`; rounding to nearest goes away from zero at the exact midpoint, so it gave `-3`; and rounding down always goes to the smaller one, so it also gave `-3`. For a positive number, truncation and rounding down give the same result; for a negative number they part ways. The `Probe` showed two evaluations for two calls, so the moment reads `on-every-use`.

When you choose the conversion way, what you should ask is whether negative values will also arrive. If they will not, two of the three ways do the same job; if they will, the rule of each is a separate decision.

**LB21.** Rounding was measured with `2.5` and `-2.5`; the other rounding rules (`.up`, `.toNearestOrEven`) lie outside this lesson.

#### Decimal Equality

Binary floating-point numbers cannot hold some simple fractions of the base-ten system exactly. `0.1`, `0.2` and `0.3` are the best-known of these: each is rounded to the nearest representable value. Adding two numbers and comparing the result with a third using `==` can therefore give an unexpected result. When you compare decimal numbers, you choose an acceptable difference limit instead of exact equality.

The block below measures this case. The first term of the sum comes from a `Probe`. The block prints the sum, the result of exact equality, and whether the difference stays under a small limit.

```swift
// Equality.swift — decimal equality
func sum(probe: Probe) -> Double {
    probe.eval(0.1) + 0.2
}
let equalProbe = Probe("decimal-sum")
let total = equalProbe.use { sum(probe: equalProbe) }
print(total)
print(total == 0.3)
print(abs(total - 0.3) < 0.000001)
equalProbe.report()
```

```
0.30000000000000004
false
true
decimal-sum: 1 evaluations, 1 uses -> on-first-use
```

The sum printed `0.30000000000000004`, exact equality gave `false`, and the comparison with a small limit came out `true`. Because `0.1` and `0.2` cannot be written exactly in base two, their sum did not meet `0.3` at the same value; the difference is in the last digit. That is why `==` is not a reliable test for computed decimal values. The measurement showed a single evaluation: the first term was taken from the `Probe` once, and the later comparisons did not recompute it, so the moment is `on-first-use`.

The size of the limit is chosen to fit the job; here `0.000001` was a sufficient measure. For values like money, where the cent matters, working with integer units is safer than a decimal type.

Choose the rounding rule by intent, not by looking at the result. If you want to cut a sum of money or a counter downward, you write `.down`; if you want the nearest value, `rounded()`; if you want only the whole part, `Int(value)`. Treating the three as the same causes a wrong result on the day the first negative value arrives. If the `Double` being converted is outside the integer range, `Int(value)` stops the program; this lesson does not run that case.

The same principle holds for decimal equality: compare the result with a limit that fits what it should be, and do not rely on exact equality. Putting the limit into a named constant keeps the same measure consistent in more than one place.

**LB22.** Equality was measured with `Double`; the result of the same sum with types such as `Float` and `Decimal` lies outside this lesson.

#### The Bounding Measurement

Look at the `unused-element` line: an element was defined inside a tuple, evaluated once, and never read. The rule says `immediately`, because the evaluation happened before the use and there was no use at all. That means a tuple element is evaluated even when it is not read; `never` appears only when the expression is never evaluated. This line also shows why the measurement condition asks for "at least two uses": with zero uses, the rule cannot tell a wasted evaluation from a real `immediately`.

**LB23.** Zero uses was left on this line on purpose; no other observation in the lesson carries zero uses.

#### Summary

- `Int`, `Double`, `Bool` and `String` are the four basic types; types are not mixed on their own.
- Conversion is explicit: `Double(count)` is an expression and is evaluated on the line where it is defined.
- `0.1 + 0.2 == 0.3` gives `false` because of the floating-point representation.
- Tuple elements are evaluated from left to right, even when they are not read.
- This lesson's moment is **immediately** (a conversion expression, once, on the `let` line).

#### Next Step

`String` appeared in this lesson only by name. The next lesson goes down into strings: what is a character, why do `count` and `utf8.count` part ways, and how many times is an expression placed inside a string set up?

### String Operations

Source: https://academia.sh/en/courses/swift/string-operations

Measures the character and byte counts of a `String` value, indexing and interpolation: an interpolated expression is rebuilt on every use.

`String` appeared in the previous lesson by name only. This lesson has three questions: how many characters does a string hold, how do you reach a particular character of a string, and how many times is an expression placed inside a string built? The third one sits on the axis of the course; the first two are the ground for understanding it.

#### The Character Model

In Swift a string is made of `Character` values, and `count` counts characters. The number of bytes the string takes in memory is asked separately with `utf8.count`. The two do not have to be equal: some Turkish letters are stored with more than one byte.

You cannot reach a string with an integer either. Writing `word[1]` is rejected by the compiler in Swift 6.4: the snippet below does not compile, which is why it has no output. The reason: characters take different numbers of bytes in memory, so the place of the nth character cannot be found without counting from the start.

```swift
let word = "ağaç"
print(word[1])
```

The right way is to use `String.Index`: `word.startIndex` points to the first character, and `word.index(after:)` to the next one. The measurement covers this too.

#### String Interpolation

Writing `"\(value)"` inside a string is string interpolation. A type that conforms to `CustomStringConvertible` asks for its own `description` property everywhere it is interpolated. Interpolation is an expression that builds the string; every time it is built, `description` is called again.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The measurement builds a small type that carries a `Probe` inside its `description` property. Two interpolations use the same value twice; also, the `Counter` type shows that a stored string does not change afterwards.

```swift
// main.swift — character model and interpolation
struct Tag: CustomStringConvertible {
    let probe: Probe
    var description: String { probe.eval("tag") }
}

struct Counter: CustomStringConvertible {
    var n: Int
    var description: String { "n=\(n)" }
}

let word = "ağaç"
print("ağaç: \(word.count) characters, \(word.utf8.count) bytes")
let second = word.index(after: word.startIndex)
print(word[second])

let descriptionProbe = Probe("description-call")
let savedProbe = Probe("stored-string")

let tag = Tag(probe: descriptionProbe)
_ = descriptionProbe.use { "first: \(tag)" }
_ = descriptionProbe.use { "second: \(tag)" }

let saved = Tag(probe: savedProbe)
let text = "\(saved)"
_ = savedProbe.use { text }
_ = savedProbe.use { text }

var counter = Counter(n: 1)
let snapshot = "\(counter)"
counter.n = 2
print("\(snapshot) \(counter)")

let allProbes = [descriptionProbe, savedProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
ağaç: 4 characters, 6 bytes
ğ
n=1 n=2
description-call: 2 evaluations, 2 uses -> on-every-use
stored-string: 1 evaluations, 2 uses -> immediately
immediately: 1
on-first-use: 0
on-every-use: 1
never: 0
```

The four-letter `ağaç` is four characters but six bytes: `ğ` and `ç` take two bytes each. `word[second]` gives the second character, `ğ`; an index is not a number but a value that knows the string.

`description-call` showed two evaluations for two uses: every interpolation rebuilt the value at the moment it was asked for. The rule reads this as `on-every-use`. An expression that builds a string is not a lazy expression, but an expression that runs everywhere it is written.

**LB24.** `ağaç` was not placed in an aligned column and stays in the string as it is: the subject of the measurement is the character and byte count of this word.

**LB25.** The `count` and `utf8.count` values were measured for this word; the counts of another word or another writing system are not a claim of this lesson.

#### Concatenation and Multiline Strings

You can join strings with the `+` operator: `"a" + "b"` produces a new string. For text that spans several lines there is the triple-quoted multiline string literal: the opening `"""` stays on its own line, the text starts on the following lines, and the closing `"""` again ends on its own line. The indentation of the closing triple quote is removed from all lines; this way you write the text to match the indentation of the code and no extra space is left in the output.

Formatting a string according to an expression means the expression is evaluated again on every call. The block below writes a function; the function wraps the incoming text in square brackets and passes the wrapping through a `Probe`. The function is called twice. On the last line a multiline literal is printed.

```swift
// Join.swift — concatenation and multiline string
func decorate(_ text: String, probe: Probe) -> String {
    probe.eval("[" + text + "]")
}
let joinProbe = Probe("concatenation")
print(joinProbe.use { decorate("a", probe: joinProbe) })
print(joinProbe.use { decorate("b", probe: joinProbe) })
let note = """
    first line
      second line
    """
print(note)
joinProbe.report()
```

```
[a]
[b]
first line
  second line
concatenation: 2 evaluations, 2 uses -> on-every-use
```

The first two lines were `[a]` and `[b]`. The next two lines are the output of the multiline string: the `first line` line was printed without indentation, the `second line` line with two spaces of indentation. The closing `"""` was indented by four spaces, and this indentation was removed from all lines; the extra two spaces of the second line itself were kept. The measurement line shows two evaluations: the `decorate` call recomputes the concatenation in its body every time, so the moment is `on-every-use`.

A multiline string literal, on the other hand, is read once as an expression; the written text is a constant and is not joined at run time. When you do the joining with `+`, the joining can happen at run time. Which one you choose depends on whether the text is constant or computed.

**LB26.** Concatenation and the multiline literal were measured with ASCII text; the platform differences in line-ending characters are outside this lesson.

#### A Substring Is a Slice, Not a String

When you take a part of a string, for example with `prefix(7)` or by slicing with a range, the result is of type `Substring`, not `String`. A `Substring` is a slice view over the source string and carries many of the string's methods. When you want to store a `Substring` for good or hand it to a place that expects a `String`, you convert it to a string with `String(...)`. This explicit conversion prevents a short-lived slice from keeping the source string alive for no reason.

The block below produces a sentence with a `Probe`, takes a slice of it, prints the type of the slice and turns the slice into a `String`. The evaluation count of the source string is followed through the slicing and the conversion.

```swift
// Slice.swift — slice and conversion to string
let sourceProbe = Probe("source-sentence")
let sentence = sourceProbe.eval("welcome world")
let head = sentence.prefix(7)
let owned = String(head)
_ = sourceProbe.use { head.count }
_ = sourceProbe.use { owned.count }
print(head, type(of: head))
print(owned, type(of: owned))
sourceProbe.report()
```

```
welcome Substring
welcome String
source-sentence: 1 evaluations, 2 uses -> immediately
```

`head` printed `welcome` and its type came out as `Substring`; `String(head)` carried the same seven-character text as a `String`. The `Probe` showed a single evaluation: the slicing and the conversion did not produce the source string again, they worked on the existing value. The slice looks at a part of the source; the conversion gives an independent copy of that part as a string. Because the evaluation was done once before use, the moment is `immediately`.

This distinction shows itself in APIs: if a function expects a `String`, you cannot give it the slice directly, you have to convert it first. The compiler enforcing this makes you manage the lifetime of the slice deliberately.

**LB27.** The slice was measured with `prefix`; that slicing with a range operator and other operations on a slice give the same type is outside this lesson.

#### Character, Unicode Scalar and Byte

There are three separate units in string counts. A character (`Character`) is the unit the reader sees as a single symbol. A Unicode scalar is a single code point in the Unicode table. A byte is the unit in which the string is stored in the UTF-8 encoding. For most ASCII characters all three are one; but they part ways in combined characters. For example, the letter `e` and the accent mark attached to it are written as two scalars, yet they appear as a single character.

The block below writes the letter `e` and the combining accent mark that follows it with the `\u{301}` escape sequence. The three counts of the string are measured inside a function over a `Probe`. The function is called with two different texts; the second text is a plain ASCII word.

```swift
// Units.swift — character, scalar and byte counts
func measure(_ text: String, probe: Probe) -> (Int, Int, Int) {
    probe.eval((text.count, text.unicodeScalars.count, text.utf8.count))
}
let unitProbe = Probe("string-units")
let combined = "e\u{301}"
print(unitProbe.use { measure(combined, probe: unitProbe) })
print(unitProbe.use { measure("bird", probe: unitProbe) })
unitProbe.report()
```

```
(1, 2, 3)
(4, 4, 4)
string-units: 2 evaluations, 2 uses -> on-every-use
```

The combined text gave `(1, 2, 3)`: one character, two Unicode scalars, three bytes. The letter `e` takes one byte in UTF-8 and the combining mark takes two. In the plain word `bird`, on the other hand, the three numbers came out as four, four and four. The two calls brought two evaluations, so the moment reads as `on-every-use`.

You can relate the character count to the symbols the reader sees, but the byte count concerns storage size. Mixing the two leads to silent errors in bounds checks. When you ask for the length of a string, choose which unit you are asking about.

**LB28.** The three counts were measured with two texts; the counts of other combined characters and emoji sequences are outside this lesson.

#### Comparison, Prefix and Suffix

`==` compares two strings character by character, but the idea of "the same character" follows Unicode: two strings written with different scalar sequences that look the same to the reader are counted equal by canonical equivalence. This makes a single `é` and a string made of `e` and a combining accent mark the same. `hasPrefix` and `hasSuffix` check the start and the end of a string; they also use the same idea of a character.

The block below compares two spellings. The single-scalar spelling goes through a `Probe`, the second one has two scalars. Then the results of `hasPrefix` and `hasSuffix` are printed.

```swift
// Compare.swift — comparison, prefix and suffix
func same(_ left: String, _ right: String, probe: Probe) -> Bool {
    probe.eval(left == right)
}
let compareProbe = Probe("string-equality")
let single = "\u{E9}"
let composed = "e\u{301}"
print(compareProbe.use { same(single, composed, probe: compareProbe) })
print(single.unicodeScalars.count, composed.unicodeScalars.count)
let word = "swift-guide"
print(word.hasPrefix("swift"), word.hasSuffix("guid"))
compareProbe.report()
```

```
true
1 2
true false
string-equality: 1 evaluations, 1 uses -> on-first-use
```

Comparing the single-scalar `é` with the two-scalar `e\u{301}` gave `true`, yet the scalar counts parted ways as `1` and `2`. So `==` looks not at scalars but at canonical equivalence: even if two strings are not the same byte by byte, they are counted equal if they stand for the same character. `hasPrefix("swift")` came out true and `hasSuffix("guid")` false, because the word ends with `guide`, not with `guid`. The `Probe` showed a single evaluation and the moment is `on-first-use`.

This matters in code that compares user input: text coming from a keyboard or a file may look the same but be written with different scalars. `==` solves this for you; a raw byte comparison would not.

**LB29.** The comparison was measured with a single combined character; case-insensitive comparison is outside this lesson.

#### Access by Index

You cannot reach a Swift string with an integer like `text[3]`. Because the byte length of characters varies, where the third character starts cannot be known without counting from the start. `String.Index` values are used instead: `text.startIndex` points to the first character, and `text.index(text.startIndex, offsetBy: 3)` to the fourth. The index computation is done by walking inside the string.

The block below takes the third character of a word by index. The word comes from a `Probe`; the function is called with two different words.

```swift
// Index.swift — access by index
func third(_ text: String, probe: Probe) -> Character {
    let source = probe.eval(text)
    let position = source.index(source.startIndex, offsetBy: 2)
    return source[position]
}
let indexProbe = Probe("index-access")
print(indexProbe.use { third("table", probe: indexProbe) })
print(indexProbe.use { third("chair", probe: indexProbe) })
indexProbe.report()
```

```
b
a
index-access: 2 evaluations, 2 uses -> on-every-use
```

The third character came out as `b` in the word `table` and `a` in the word `chair`. The index was found in each word by walking from the start: `index(_:offsetBy:)` passed over the characters one by one, because how many bytes a character takes is not known in advance. This is why there is no integer subscript; if there were one, a slow search would hide silently in a long text. The `Probe` showed two evaluations for two calls and the moment reads as `on-every-use`.

If access by index is a frequent job, the string can be turned into an array of characters with an `Array(text)` conversion and read with integers; but this means copying the whole string once.

The index type being a separate type also gives some safety: using an index taken from one string in another string may give a wrong result. Keeping the line that computes the index and the line that uses it tied to the same string is a good habit for this reason. Using a single local copy named `source` in the same function guarantees that the index and the string look at the same value.

The same mechanism applies to reaching the last character of a string: `text.index(before: text.endIndex)` gives the index of the last character. Because index computations walk from the start or from the end, in long strings it is cheaper to compute them once and store them than to repeat them inside a loop. The measurement shows that the word was taken again on every call.

**LB30.** Index access was measured with ASCII words; the cases where an out-of-range index stops the program are not run in this lesson.

#### The Limiting Measurement

If a string is built once and stored in a `let`, the table changes. `stored-string` showed one evaluation for two uses: `"\(saved)"` ran only on the line where it was stored, and the following two reads only read the string. The rule says `immediately`.

This also has a cost. The `snapshot` string was built before `counter` changed, and a value that changes after the string is built does not show in it: `snapshot` is still `n=1`, and the rebuilt string is `n=2`. A stored string is a photograph; interpolation is a photograph taken anew every time.

**LB31.** `Counter` is a structure and `snapshot` carries its value at the moment it was built; the behavior of class types was not measured in this lesson.

#### Summary

- `count` counts characters and `utf8.count` counts bytes; `ağaç` is 4 characters and 6 bytes.
- A string is not indexed with an integer; `String.Index` is used.
- Interpolation calls the `description` property again on every evaluation.
- A stored string is a single evaluation and does not reflect a value that changes later.
- The moment of this lesson: **on every use** (two `description` calls in two interpolations).

#### Next Step

Strings also join and compare through operators such as `+` and `==`. The next lesson looks at operators: is the right-hand side of an operator always evaluated?

### Operators

Source: https://academia.sh/en/courses/swift/operators

Introduces arithmetic, comparison and range operators; measures that the right-hand side of `||`, `&&` and the ternary operator may never be evaluated.

The interpolation of a string was rebuilt on every use. An operator also joins two expressions; the question is this: are both of them evaluated? In an earlier course (M10/K03) "how many times did it run" was a number; this course asks for a moment, and the most striking moment among operators is `never`.

#### Arithmetic, Comparison and Range

The arithmetic operators are `+`, `-`, `*`, `/` and `%`. Dividing two `Int` values gives an `Int`: `7 / 2` is 3 and `7 % 2` is the remainder of the division, 1; `7.0 / 2` gives 3.5. Comparison operators such as `<`, `>` and `==` return a `Bool`. Range operators build a sequence of values: `1...4` includes both ends, `1..<4` leaves the upper end out. `contains` tells whether a range holds a value.

Operator precedence is like in mathematics: multiplication and division come before addition, and parentheses change the order. Because comparison operators return a `Bool`, they can be an `if` condition directly; we will use this in the next lesson. `==` asks whether two values are equal, while a single `=` assigns, and mixing the two up is a common mistake. Ranges are values too: `1...4` can be assigned to a constant, walked in a loop or turned into an array with `Array(...)`.

The measuring tool is again the same helper file. Each `Probe` counts how many times the expression it wraps is evaluated and how many times it is used; the relation between the two gives the moment.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

Now the measurement block. Each line shows a result, then three `Probe` objects print their own reports. While reading, look at this: first the results of the operators, then the three expressions whose right-hand side is measured. Because `isOpen` is true, the right side of `||` is never needed; the same goes for the branch of the ternary operator (`condition ? a : b`) that is not chosen.

```swift
// main.swift — results of operators and their right-hand side
print(7 / 2, 7 % 2, 7.0 / 2)
print((1...4).contains(4), (1..<4).contains(4))
print(Array(1..<4))

let orProbe = Probe("or-operator-right")
let andProbe = Probe("and-operator-right-true")
let ternaryProbe = Probe("ternary-branch")

let isOpen = true
_ = orProbe.use { isOpen || orProbe.eval(true) }
_ = orProbe.use { isOpen || orProbe.eval(true) }
_ = andProbe.use { isOpen && andProbe.eval(true) }
_ = andProbe.use { isOpen && andProbe.eval(true) }
_ = ternaryProbe.use { isOpen ? 1 : ternaryProbe.eval(2) }
_ = ternaryProbe.use { isOpen ? 1 : ternaryProbe.eval(2) }

let allProbes = [orProbe, andProbe, ternaryProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
3 1 3.5
true false
[1, 2, 3]
or-operator-right: 0 evaluations, 2 uses -> never
and-operator-right-true: 2 evaluations, 2 uses -> on-every-use
ternary-branch: 0 evaluations, 2 uses -> never
immediately: 0
on-first-use: 0
on-every-use: 1
never: 2
```

`or-operator-right` showed zero evaluations in two uses: while `isOpen` is true, `||` does not look at the right-hand side. The branch of the ternary operator that is not chosen is the same: `ternary-branch` is `never` in two uses. `&&`, on the other hand, moves on to the right because the left side is true, and the right-hand side is evaluated again on every use. Three lines, two results: the same right-hand expression is evaluated either never or every time, depending on the left side of the operator.

**LB32.** `isOpen` is a constant; the evaluation of the right-hand side for another value of the left side was not measured in this lesson.

**LB33.** The results of `7 / 2` and `7 % 2` are seen in the output of this block; other operator precedences were not measured.

#### Range Operators

Swift offers two range operators: the closed range `1...3` includes both ends, the half-open range `1..<3` leaves the upper end out. Ranges can be used in a loop, in slicing or in a comparison, and can be turned into an array with `Array(...)`. The end values of a range are ordinary expressions; the operator only joins these two ends.

The block below builds two ranges. The upper end of the closed range comes from one `Probe`, and the upper end of the half-open range from another. Each range is read twice: once as `count`, once as an array. Then the contents of the two ranges are printed.

```swift
// Range.swift — closed and half-open range
let closedProbe = Probe("closed-range")
let halfProbe = Probe("half-open-range")
let closed = 1...closedProbe.eval(3)
let half = 1..<halfProbe.eval(3)
_ = closedProbe.use { closed.count }
_ = closedProbe.use { Array(closed) }
_ = halfProbe.use { half.count }
_ = halfProbe.use { Array(half) }
print(Array(closed), Array(half))
print(closed.contains(3), half.contains(3))
closedProbe.report()
halfProbe.report()
```

```
[1, 2, 3] [1, 2]
true false
closed-range: 1 evaluations, 2 uses -> immediately
half-open-range: 1 evaluations, 2 uses -> immediately
```

The closed range gave `[1, 2, 3]` and the half-open range gave `[1, 2]`; the same upper end 3 stayed inside in one place and outside in the other. The `contains(3)` line confirms this. Both `Probe` objects showed a single evaluation: the upper end was computed once while the range was being built, and the later reads did not compute it again. Because a range is a value, the expression that computes its end runs on the definition line; the reads use the ready value.

The safety of range operators comes from here: the end expression does not short-circuit, all of it is computed immediately. This differs from the `&&` and `||` operators we saw earlier, because their right side depended on the condition.

**LB34.** Ranges were measured with integer ends and `Int` values; the behavior of decimal ranges and of ranges that skip steps with `stride` is outside this lesson.

#### Compound Assignment and Operator Precedence

Compound assignment operators read a variable and write the new value to the same place: `score += 3` and `score = score + 3` are for the same job. `-=`, `*=` and `/=` follow the same pattern. Operators also have an order of precedence: multiplication works before addition, so `2 + 3 * 4` gives 14; parentheses change this order and `(2 + 3) * 4` gives 20.

What is to be measured is that the right-hand side of a compound assignment is evaluated again each time it runs. The block below increases a `score` variable twice. Each increase includes a multiplier that comes from a `Probe`. Both results of precedence are printed in the same block.

```swift
// Compound.swift — compound assignment and precedence
let stepProbe = Probe("step-multiplier")
var score = 2
_ = stepProbe.use { score += stepProbe.eval(3) * 2 }
_ = stepProbe.use { score += stepProbe.eval(3) * 2 }
print(score)
print(2 + 3 * 4, (2 + 3) * 4)
stepProbe.report()
```

```
14
14 20
step-multiplier: 2 evaluations, 2 uses -> on-every-use
```

`score` started at 2 and became 14 after two increases; each increase added 6, which is `3 * 2`. The expression `2 + 3 * 4` came out as 14 and the parenthesized form as 20. The measurement line showed two evaluations: the right-hand side of a compound assignment is computed again every time it runs. This is why the moment is `on-every-use`; `+=` was written once but ran twice.

You can read compound assignment as an abbreviation, but the right-hand side of the abbreviation is an expression that is evaluated again. If the right-hand side is a call with side effects, you should expect this on every run of the assignment.

**LB35.** Compound assignment was measured with `Int`; the behavior of `+=` on decimal numbers or strings is outside this lesson.

#### Division and Remainder

Integer division truncates the result to an integer: `7 / 2` gives 3, not 3.5. The `%` operator returns the remainder of the division: `7 % 2` gives 1. With negative numbers the sign of the remainder follows the sign of the dividend: `-7 % 3` comes out as -1. If you want a fractional result, you write both sides as decimals: `7.0 / 2` gives 3.5. Dividing by zero stops the program; the lesson does not run it.

The block below writes a function that uses an integer both as the dividend and for the divisor. The divisor is read twice through a `Probe`: once for the quotient, once for the remainder. The function is called with one positive and one negative number.

```swift
// Division.swift — division and remainder
func divide(_ number: Int, probe: Probe) -> (Int, Int) {
    (number / probe.eval(2), number % probe.eval(2))
}
let divisorProbe = Probe("divisor")
print(divisorProbe.use { divide(7, probe: divisorProbe) })
print(divisorProbe.use { divide(-7, probe: divisorProbe) })
print(7.0 / 2, -7 % 3)
divisorProbe.report()
```

```
(3, 1)
(-3, -1)
3.5 -1
divisor: 4 evaluations, 2 uses -> on-every-use
```

`divide(7)` gave `(3, 1)` and `divide(-7)` gave `(-3, -1)`: the quotient was truncated toward zero and the remainder took the sign of the dividend. The decimal division came out as 3.5 and `-7 % 3` as -1. There are four evaluations in the measurement line, because each call writes the divisor expression twice. So the two calls brought four evaluations and the moment reads as `on-every-use`.

There is also a small trap this measurement shows: writing the same expression in two places means two evaluations. Computing the value once and taking it into a constant both lowers the count and simplifies the reading.

**LB36.** Division and remainder were measured with `Int`; the stopping cases such as division by zero and `Int.min / -1` are not run in this lesson.

#### The Ternary Conditional Operator

The ternary operator in the form `condition ? a : b` picks one of two values according to the condition. If the condition is `true`, `a` is the result, otherwise `b`. The operator has three operands and their order is always the same: first the condition, then the "if true" expression, then the "if false" expression. It is the short form of a small `if`-`else` that produces a value.

The rule to be measured here is that the branch that is not chosen never runs. The block below ties each of the two branches to a separate `Probe` and runs the operator twice with a `true` condition.

```swift
// Ternary.swift — ternary conditional operator
let yesProbe = Probe("true-branch")
let noProbe = Probe("false-branch")
func choose(_ flag: Bool, yes: Probe, no: Probe) -> Int {
    flag ? yes.eval(10) : no.eval(20)
}
_ = yesProbe.use { choose(true, yes: yesProbe, no: noProbe) }
_ = noProbe.use { choose(true, yes: yesProbe, no: noProbe) }
print(choose(true, yes: yesProbe, no: noProbe))
yesProbe.report()
noProbe.report()
```

```
10
true-branch: 3 evaluations, 1 uses -> on-every-use
false-branch: 0 evaluations, 1 uses -> never
```

`choose(true)` gave `10` on every call. `true-branch` showed three evaluations: the two `use` calls and the call inside the last `print`, all three went to the true branch. `false-branch`, on the other hand, came out `never` with zero evaluations, because it was not chosen in any call. When the condition is true, the expression of the false branch is compiled but never run.

This rests on the same rule as `&&` and `||`: when the result is known, the remaining expression is not evaluated. When you put a call with side effects in a branch of the ternary operator, you know that call will run only when that branch is chosen.

Because the ternary operator is an expression, it produces a value; so it can be assigned directly to a constant or given to a function as an argument. When the condition grows long or the branches get complicated, `if`-`else` and a separate constant are the way to write the same rule more readably.

If a branch has no side effect, its not being chosen goes unnoticed; if it does, for example if it increases a counter or changes a record, knowing that this effect never happens in the branch that is not chosen prevents a mistake. The measurement showed exactly this difference with a number.

**LB37.** The ternary operator was measured with two `Int` branches; the readability of nested ternary operators is outside this lesson.

#### The Limiting Measurement

Short-circuit evaluation comes from the `||` and `&&` operators taking their second parameter with `@autoclosure`. An operator is a function that takes its second parameter with `@autoclosure`; if the right-hand side is not needed, it is never called. A function that does the same job but takes its second parameter as an ordinary `Bool` evaluates the right-hand side before the call. Below, these two signatures stand side by side. We call both of them twice with a false left side; so the right-hand side does not need to be evaluated, and the difference comes only from the signature.

```swift
// main.swift — type of the right side: Bool and autoclosure
func both(_ left: Bool, _ right: Bool) -> Bool { left && right }
func lazyBoth(_ left: Bool, _ right: @autoclosure () -> Bool) -> Bool { left && right() }

let eagerProbe = Probe("both-right")
let autoProbe = Probe("lazyboth-right")

_ = eagerProbe.use { both(false, eagerProbe.eval(true)) }
_ = eagerProbe.use { both(false, eagerProbe.eval(true)) }
_ = autoProbe.use { lazyBoth(false, autoProbe.eval(true)) }
_ = autoProbe.use { lazyBoth(false, autoProbe.eval(true)) }

let allProbes = [eagerProbe, autoProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
both-right: 2 evaluations, 2 uses -> on-every-use
lazyboth-right: 0 evaluations, 2 uses -> never
immediately: 0
on-first-use: 0
on-every-use: 1
never: 1
```

The bodies of the two functions are the same: `left && right`. `both` evaluates the right-hand side before the call, even though the body does not use it because `left` is false; the rule says `on-every-use`. `lazyBoth` wraps the right-hand side in a closure and the body never touches it: `never`. What makes the difference is not the operator but the parameter type.

**LB38.** `@autoclosure` was measured in this lesson only as a signature that defers the right-hand side; closure details are left to the closures lesson.

The practical result learned here is this: if there is a call with side effects on the right-hand side of an expression, assuming that the call will run unconditionally is wrong. Conditions built with `&&` and `||` are read in order, and if the left-hand expression has decided the result, the right-hand one never runs. If you want a computation to be done in every case, take it into a constant outside the operator and use the result in the operator.

#### Summary

- `/` gives an `Int` for two `Int` values and `%` gives the remainder; `...` and `..<` build ranges.
- The right-hand side of `||`, `&&` and the ternary operator is never evaluated if it is not needed.
- Short-circuit lives not in the operator but in the second parameter being an `@autoclosure`.
- If you write the same body without `@autoclosure`, the right-hand side is evaluated on every call.
- The moment of this lesson: **never** (the right side of the `||` operator when the left side is true).

#### Next Step

There is another place where an expression is never evaluated: the branches of a `switch` after the first match. The next lesson looks at control flow, conditions and loops.

### Control Flow

Source: https://academia.sh/en/courses/swift/control-flow

Introduces conditions, loops and the pattern-matching `switch` statement; measures that `where` conditions after the first match are never evaluated.

Operators joined two expressions, and the right-hand side was never evaluated when it was not needed. Control flow carries the same idea one step up: conditions decide which branch runs, and a construct that has found the first suitable branch does not look at the rest. The question of this lesson is this: in a chain, when are the conditions that come after a match evaluated?

#### Conditions, Loops and switch

`if` asks a `Bool` condition; an `else if` chain tries the conditions from top to bottom. `for n in 1...3` runs the body for every value in a range, and `while` goes on as long as the condition is true. `switch` compares a value with patterns. A `case` can be a value, a range, a tuple or a condition decorated with `where`. In Swift the `case` bodies do not fall through to the next one; the first match runs and the `switch` ends.

A `switch` has to be exhaustive: every possible value must be covered by a `case`, or there must be a `default`. The snippet below handles only 1 and 2 for an `Int`. This snippet does not compile in Swift 6.4; the compiler rejects it, which is why it has no output.

```swift
let n = 3
switch n {
case 1: print("one")
case 2: print("two")
}
```

The error is a real guarantee: a `switch` that does not cover a newly added value does not compile. The fix is to add a `default` or to catch the remaining values with a pattern.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The measurement block builds two chains. In the first, the `grade` function evaluates a score of 75: the first condition is false, the second is true and the third is never reached. In the second, the `describe` function tests the value `-5` with a `switch`: the `where` condition of the first `case` is true, and the `where` condition of the next `case` is never asked.

```swift
// main.swift — what follows the first match in a chain
func grade(_ score: Int, _ second: Probe, _ third: Probe) -> String {
    if score >= 90 {
        return "A"
    } else if second.eval(score >= 70) {
        return "B"
    } else if third.eval(score >= 50) {
        return "C"
    }
    return "F"
}

func describe(_ n: Int, _ first: Probe, _ later: Probe) -> String {
    switch n {
    case let x where first.eval(x < 0):
        return "negative"
    case let x where later.eval(x > 100):
        return "large"
    default:
        return "other"
    }
}

for n in 1...3 { print("step", n) }

let secondProbe = Probe("else-if-second-condition")
let thirdProbe = Probe("else-if-third-condition")
let firstWhereProbe = Probe("switch-first-where")
let laterWhereProbe = Probe("switch-later-where")

for _ in 1...2 {
    let letter = secondProbe.use { thirdProbe.use { grade(75, secondProbe, thirdProbe) } }
    print(letter)
    let kind = firstWhereProbe.use { laterWhereProbe.use { describe(-5, firstWhereProbe, laterWhereProbe) } }
    print(kind)
}

let allProbes = [secondProbe, thirdProbe, firstWhereProbe, laterWhereProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
step 1
step 2
step 3
B
negative
B
negative
else-if-second-condition: 2 evaluations, 2 uses -> on-every-use
else-if-third-condition: 0 evaluations, 2 uses -> never
switch-first-where: 2 evaluations, 2 uses -> on-every-use
switch-later-where: 0 evaluations, 2 uses -> never
immediately: 0
on-first-use: 0
on-every-use: 2
never: 2
```

`else-if-second-condition` was evaluated on every call, because the first condition was false and so the chain came to it. `else-if-third-condition`, on the other hand, came out `never` in both calls: the second condition was already true and the chain ended there. The same holds for `switch`: the first `where` was tested every time, the later `where` was never tested. So a side effect inside a `where` condition never happens if an earlier `case` matched.

**LB39.** The measurement was done with a single input value (75 and -5); for other inputs, which condition stays `never` changes.

**LB40.** That `switch` is tried from top to bottom in source order was concluded from the measurement; whether the compiler changes the order was not measured separately.

#### Early Exit with guard

`guard` verifies a condition and forces an exit from the scope if the condition does not hold. The syntax is `guard condition else { exit }`; the `else` block has to end with `return`, `break`, `continue` or a call that stops the program. If the condition holds, control continues after the `guard` line, and the names bound in the condition are visible in the rest of that scope. It does the same job as `if`, but turns the intent around: the unwanted case is ruled out first, then the real work is written on a flat path.

The block below writes a function that accepts a positive number. The valid path writes to one `Probe`, the invalid path to another. The function is called with three numbers, and before each call the two `Probe` objects each record a use.

```swift
// Guard.swift — early exit with guard
func check(_ number: Int, valid: Probe, invalid: Probe) -> String {
    guard number > 0 else { return invalid.eval("invalid") }
    return valid.eval("valid")
}
func observe<T>(_ watched: [Probe], _ work: () -> T) -> T {
    for probe in watched { _ = probe.use { 0 } }
    return work()
}
let validProbe = Probe("valid-path")
let invalidProbe = Probe("invalid-path")
for number in [5, -2, 7] {
    print(observe([validProbe, invalidProbe]) {
        check(number, valid: validProbe, invalid: invalidProbe)
    })
}
validProbe.report()
invalidProbe.report()
```

```
valid
invalid
valid
valid-path: 2 evaluations, 3 uses -> on-every-use
invalid-path: 1 evaluations, 3 uses -> on-first-use
```

The three numbers gave the results `valid`, `invalid`, `valid`. The valid path ran twice and the invalid path once: `valid-path` came out `on-every-use` with two evaluations and three uses, and `invalid-path` came out `on-first-use` with one evaluation and three uses. The use count came out three, because `observe` recorded a use before each call. The expression a path produces is evaluated only when that path is chosen; the expression of the path that is not chosen never runs.

`guard` makes it readable which path runs at which moment: the exceptional path stands at the very start, and the remaining lines run only when the condition holds. The measurement confirms this reading.

**LB41.** `guard` was measured only with an integer condition; using `guard let` with optional values is the job of a later topic.

#### switch Patterns

The `switch` statement compares a value with patterns in order. Patterns do not have to be only constants: tuple patterns compare several values at once, `let` binds a value, and `where` adds a condition. For example, `case (let x, 0)` catches every tuple whose second element is zero and binds the first element to the name `x`. The first matching case runs and the others are never evaluated.

The block below writes a function that finds the class of a point. Each of the three cases writes to its own `Probe`. The function is called with three points: the origin twice, a point on the horizontal axis once; the third case never matches.

```swift
// Pattern.swift — switch patterns
func classify(_ x: Int, _ y: Int, watched: [Probe]) -> String {
    switch (x, y) {
    case (0, 0):
        return watched[0].eval("origin")
    case (let along, 0):
        return watched[1].eval("horizontal \(along)")
    case (_, let height) where height > 5:
        return watched[2].eval("high \(height)")
    default:
        return "other"
    }
}
func observe<T>(_ watched: [Probe], _ work: () -> T) -> T {
    for probe in watched { _ = probe.use { 0 } }
    return work()
}
let originProbe = Probe("origin-case")
let axisProbe = Probe("axis-case")
let highProbe = Probe("high-case")
let cases = [originProbe, axisProbe, highProbe]
for point in [(0, 0), (4, 0), (0, 0)] {
    print(observe(cases) { classify(point.0, point.1, watched: cases) })
}
for probe in cases { probe.report() }
```

```
origin
horizontal 4
origin
origin-case: 2 evaluations, 3 uses -> on-every-use
axis-case: 1 evaluations, 3 uses -> on-first-use
high-case: 0 evaluations, 3 uses -> never
```

The three calls gave the results `origin`, `horizontal 4`, `origin`. `origin-case` came out `on-every-use` with two evaluations, `axis-case` `on-first-use` with a single evaluation, and `high-case` `never` with zero evaluations. The third case was never tried despite its `where` condition, because the first two cases had already caught the points. So `switch` looks in order, takes the first match and does not touch the rest.

This rule matters when you order patterns: if you write a general case before a specific case, the specific case never runs. The compiler rejects missing coverage as an error, but in some cases it cannot find a wrong order.

**LB42.** Patterns were measured with tuples and `where`; enumeration cases and range patterns are outside this lesson.

#### Labeled Statements

In nested loops `break` ends only the innermost loop. To end the outer loop you give the loop a label: `outer: for row in 1...3 { ... }`. A `break outer` inside jumps to this label and the outer loop ends. `continue` with the same label moves to the next iteration of the outer loop. The label is the way to write explicitly which loop you mean.

The block below writes a function that looks for a particular product in a multiplication table. Each product is computed through a `Probe`; so the number of iterations run is measured. The function is called with two targets.

```swift
// Label.swift — search with a labeled break
func search(target: Int, probe: Probe) -> String {
    var found = "none"
    outer: for row in 1...3 {
        for col in 1...3 {
            if probe.eval(row * col) == target {
                found = "\(row)x\(col)"
                break outer
            }
        }
    }
    return found
}
let searchProbe = Probe("product-search")
print(searchProbe.use { search(target: 4, probe: searchProbe) })
print(searchProbe.use { search(target: 6, probe: searchProbe) })
searchProbe.report()
```

```
2x2
2x3
product-search: 11 evaluations, 2 uses -> on-every-use
```

The first search found `2x2`, the second `2x3`. Eleven evaluations were needed in total: five products were computed in the first search (1, 2, 3, 2, 4), and six in the second (1, 2, 3, 2, 4, 6). `break outer` ended both loops at once as soon as the product was found, so the remaining products were never computed. An unlabeled `break` would have ended only the inner loop, and the outer loop would have continued with the next row. The moment reads as `on-every-use`.

The labeled exit protects the search from unnecessary products. The label also shows how many loops the code skips; the reader knows from its name which loop ends.

**LB43.** The labeled `break` was measured with two nested loops; using a label with `continue` is outside this lesson.

#### At Least One Round with repeat-while

A `while` loop checks the condition first; if the condition is false from the start, the body never runs. `repeat-while` turns this around: the body runs first and the condition is checked afterwards. So the body runs at least once, whatever the condition is. When you need to read a value at least once, or to do an action once and then decide whether to go on, this form is the right tool.

The block below runs two loops with the same condition that is false from the start. Each body increases a counter by a one that comes from a `Probe`. One is written with `while`, the other with `repeat-while`.

```swift
// Repeat.swift — repeat-while runs at least one round
let whileProbe = Probe("while-body")
let repeatProbe = Probe("repeat-body")
var whileCount = 0
var repeatCount = 0
_ = whileProbe.use {
    while whileCount < 0 { whileCount += whileProbe.eval(1) }
}
_ = repeatProbe.use {
    repeat { repeatCount += repeatProbe.eval(1) } while repeatCount < 0
}
print(whileCount, repeatCount)
whileProbe.report()
repeatProbe.report()
```

```
0 1
while-body: 0 evaluations, 1 uses -> never
repeat-body: 1 evaluations, 1 uses -> on-first-use
```

The two loops with the same false-from-the-start condition gave `0 1`: `while` never increased the counter, `repeat-while` increased it once. `while-body` came out `never` with zero evaluations, and `repeat-body` `on-first-use` with one evaluation. In a `repeat-while` loop the condition is checked after the body, so the expression of the body ran once even though the condition was false.

The question of choice is this: does the body have to run at least once before the condition? If you read a value and decide afterwards, `repeat-while` is the right tool; if you want to do nothing when the condition does not hold from the start, `while` is.

**LB44.** `repeat-while` was measured with a condition that is false from the start; that the two forms give the same result in loops where the condition stays true is outside this lesson.

#### The Limiting Measurement

The conditions in a chain were asked once and dropped. In loops the condition is asked again on every round. `for ... where` evaluates the condition on every iteration; so the expression inside `where` is `on-every-use` in this line. `while` carries a subtle detail: the condition is evaluated one more time when leaving the loop, because the only way out of the loop is the condition returning `false`. A `while` that lasts three rounds therefore evaluates the condition four times.

```swift
// main.swift — loop conditions
let whereProbe = Probe("for-where-condition")
let whileProbe = Probe("while-condition")

for _ in 1...2 {
    var evens: [Int] = []
    whereProbe.use {
        for n in 1...4 where whereProbe.eval(n % 2 == 0) { evens.append(n) }
    }
    print(evens)
    whileProbe.use {
        var i = 0
        while whileProbe.eval(i < 3) { i += 1 }
    }
}

let allProbes = [whereProbe, whileProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
[2, 4]
[2, 4]
for-where-condition: 8 evaluations, 2 uses -> on-every-use
while-condition: 8 evaluations, 2 uses -> on-every-use
immediately: 0
on-first-use: 0
on-every-use: 2
never: 0
```

Over the two rounds, the `for ... where` condition was evaluated eight times, once for each of four iterations per round. The `while` condition got eight evaluations although it made three iterations in each of the two rounds: the number of iterations plus one. The extra evaluation is the `false` query that ends the loop.

**LB45.** The "iterations plus one" result for `while` was measured in this three-iteration example; a loop that exits with `break` or `return` has no extra query, but this was not measured in this lesson.

#### Summary

- The `if` / `else if` chain tries the conditions from top to bottom and stops at the first true one.
- A `switch` has to be exhaustive; a missing `case` is rejected by the compiler.
- The `where` conditions and `else if` conditions after the first match are never evaluated.
- The `for ... where` condition is evaluated on every iteration, and the `while` condition one more time than the number of iterations.
- The moment of this lesson: **never** (the `where` after a match).

#### Next Step

A condition only tells whether a branch runs. There are also expressions whose evaluation moment during a call is the question: the default argument of a function. The next lesson measures argument labels and default values.

### Functions

Source: https://academia.sh/en/courses/swift/functions

Introduces argument labels, default values, multiple returns through a tuple and the `inout` parameter; measures that a default argument expression is evaluated on every call.

In control flow, conditions were evaluated only when needed. In functions the question goes one step further: when is the argument of a call evaluated, and when is the default value of a parameter? A function in Swift is designed to look like a sentence the caller can read; the measurement in this lesson shows the evaluation order behind that sentence.

#### Labels, Defaults and Return

In Swift every parameter has an argument label, and it is written at the call. In the definition `func move(from start: Int, to end: Int)`, `from` and `to` are the labels the caller sees, while `start` and `end` are the names the body uses. If you write an underscore instead of a label, the call has no label: `func pad(_ text: String)`. Adding `= value` to a parameter defines a default argument; if the caller does not give that parameter, the default expression is used.

A function can return a tuple to return several values: `-> (low: Int, high: Int)`. A labeled tuple is read on the caller's side as `result.low`. An `inout` parameter lets the function change the caller's variable; the variable is prefixed with `&` at the call and has to be a `var`.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The measurement block first runs these four features. Then it builds two functions with the same body: `pad` takes its default width from a `Probe` when the caller does not give one, while `padGiven` has the same default but we give the width ourselves on every call. The functions are marked `@MainActor`, because the default expression reads the top-level `Probe`, and under the Swift 6 rules a `Probe` can be read only from the main actor.

```swift
// main.swift — label, default, tuple and inout
func move(from start: Int, to end: Int) -> Int { end - start }
func bounds(of values: [Int]) -> (low: Int, high: Int) {
    (values.min() ?? 0, values.max() ?? 0)
}
func increment(_ value: inout Int) { value += 1 }

print(move(from: 2, to: 5))
let found = bounds(of: [3, 1, 2])
print(found.low, found.high)
var total = 0
increment(&total)
increment(&total)
print(total)

let defaultProbe = Probe("default-expression")
let givenProbe = Probe("default-when-given")

@MainActor func pad(_ text: String, width: Int = defaultProbe.eval(6)) -> String {
    String(repeating: "*", count: width) + text
}

@MainActor func padGiven(_ text: String, width: Int = givenProbe.eval(6)) -> String {
    String(repeating: "*", count: width) + text
}

print(defaultProbe.use { pad("a") })
print(defaultProbe.use { pad("b") })
print(givenProbe.use { padGiven("c", width: 2) })
print(givenProbe.use { padGiven("d", width: 2) })

let allProbes = [defaultProbe, givenProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
3
1 3
2
******a
******b
**c
**d
default-expression: 2 evaluations, 2 uses -> on-every-use
default-when-given: 0 evaluations, 2 uses -> never
immediately: 0
on-first-use: 0
on-every-use: 1
never: 1
```

The `move` call gave 3, the `bounds` tuple was read as `1 3`, and the two `increment` calls made `total` 2. The key lines of the measurement are at the end. `default-expression` was evaluated twice in two calls: a default expression is not computed once at the function definition and stored, it runs again on every call, and its result is `on-every-use`. `default-when-given` showed zero evaluations in two calls, because the caller gave the width itself and the default expression was never reached: `never`.

**LB46.** The default argument expression was measured in a `@MainActor` function and only for a constant integer; the same result for other types or in a `nonisolated` context is not a claim of this lesson.

**LB47.** Whether the default expression runs in the caller's context or the callee's context is not distinguished in this lesson; what was measured is how many times and when it was evaluated.

#### Variadic Parameters

If you write three dots after the type of a parameter, the function takes as many arguments as you like at that point: `func sumAll(of numbers: Int...) -> Int`. Inside the function body `numbers` is an ordinary `[Int]` array. At the call you write the arguments separated by commas; giving no argument at all is allowed too, and then the array arrives empty. A function can have more than one variadic parameter; the parameter that comes after the first one has to carry an argument label.

Arguments are evaluated before the call; three arguments mean three expressions. The block below makes two calls that pass each argument through a `Probe`, and adds one call without arguments.

```swift
// Variadic.swift — variadic parameters
func sumAll(of numbers: Int...) -> Int {
    numbers.reduce(0, +)
}
let variadicProbe = Probe("variadic-count")
print(variadicProbe.use {
    sumAll(of: variadicProbe.eval(1), variadicProbe.eval(2), variadicProbe.eval(3))
})
print(variadicProbe.use {
    sumAll(of: variadicProbe.eval(4), variadicProbe.eval(5))
})
print(sumAll())
variadicProbe.report()
```

```
6
9
0
variadic-count: 5 evaluations, 2 uses -> on-every-use
```

The sum of three numbers gave 6, the sum of two numbers 9, and the call without arguments 0. The `Probe` showed five evaluations: three in the first call and two in the second. Each argument is its own expression and is computed before the call; the function body receives it ready as an array. So the moment reads `on-every-use`.

A variadic parameter simplifies the caller's side, because no array has to be built. The number of arguments changes with the call; the measurement shows that this change also changes the number of evaluations.

**LB48.** The variadic parameter was measured with `Int`; Swift has no way to spread an array into a variadic parameter; if an array is needed, the parameter is declared as `[Int]`.

#### A Nested Function Captures Its Surroundings

You can define another function inside a function. The inner function sees the local variables and parameters of the outer function and captures them. If the outer function returns the inner function, the captured variables go on living after the outer function has finished. This is the way to build a counter that carries its own state on every call.

The block below writes a function named `makeCounter`. The function takes a start value; the inner function `advance` increases the number by one on every call, passes it through a `Probe`, and the function returns the inner function. Two independent counters are built: the first is called twice, the second once.

```swift
// Counter.swift — a nested function carries state
func makeCounter(start: Int, probe: Probe) -> () -> Int {
    var current = start
    func advance() -> Int {
        current += 1
        return probe.eval(current)
    }
    return advance
}
let nestedProbe = Probe("nested-function")
let first = makeCounter(start: 10, probe: nestedProbe)
let second = makeCounter(start: 100, probe: nestedProbe)
print(nestedProbe.use { first() })
print(nestedProbe.use { first() })
print(nestedProbe.use { second() })
nestedProbe.report()
```

```
11
12
101
nested-function: 3 evaluations, 3 uses -> on-every-use
```

The first counter gave 11 and 12, the second counter 101. Although the two counters came out of the same function, each captured a separate `current`; while one advanced, the other was not affected. Three calls brought three evaluations, and the moment is `on-every-use`. Even after `makeCounter` has finished, `current` is alive, because the inner function holds it.

This prepares the topic of the next lesson: a nested function is a closure that has been given a name. The capture rules are the same.

**LB49.** The nested function captured an `Int` state; cases where the captured value is a class instance are outside this lesson.

#### inout Writes Back

An `inout` parameter lets the function change the caller's variable. The mechanism is "copy, change, write back": the function takes a copy of the variable, changes it as much as it wants in the body, and when the function ends it writes the result back to the variable in one go. If the variable has an observer (`didSet`), the observer runs once at the write-back, not at each change in the body. A direct assignment, on the other hand, runs the observer on every line.

The block below does the same job in two ways: one increments twice with a function that has an `inout` parameter, the other writes the two increments directly. Both variables have a `didSet` observer, and each observer writes to its own `Probe`. Both ways are run for two rounds.

```swift
// Inout.swift — inout write-back
func addTwice(_ value: inout Int) {
    value += 1
    value += 1
}
let viaCallProbe = Probe("inout-observer")
let directProbe = Probe("direct-observer")
var viaCall = 0 { didSet { _ = viaCallProbe.eval(viaCall) } }
var direct = 0 { didSet { _ = directProbe.eval(direct) } }
_ = viaCallProbe.use { addTwice(&viaCall) }
_ = viaCallProbe.use { addTwice(&viaCall) }
_ = directProbe.use { direct += 1; direct += 1 }
_ = directProbe.use { direct += 1; direct += 1 }
print(viaCall, direct)
viaCallProbe.report()
directProbe.report()
```

```
4 4
inout-observer: 2 evaluations, 2 uses -> on-every-use
direct-observer: 4 evaluations, 2 uses -> on-every-use
```

Both variables became 4, but the observer counts diverged: the `inout` way showed two evaluations, the direct way four evaluations. `addTwice` incremented twice in the body; the observer ran at the write-back, once per call. In the direct way each `+=` triggered its own observer. Both lines read `on-every-use`, but their counts differ.

This difference needs care when `inout` and an observer come together: there may be intermediate values the observer does not see. If you want to see the intermediate states, write directly; if you want only the result, `inout` is enough.

**LB50.** The observer count was measured with a top-level variable; that `inout` write-back gives the same count on class properties and struct properties is outside this lesson.

#### Function Type and Function as a Value

Every function has a type: the combination of the parameter types and the return type. The type of the function `func triple(_ n: Int) -> Int` is written `(Int) -> Int`. This type is used like an ordinary type: you can assign it to a constant, write it as a parameter type, or return it from another function. Assigning a function to a constant does not call it; it only carries it as a value. A call is made only with parentheses.

The block below assigns the `triple` function to a constant, prints its type, and passes it as an argument to another function named `apply`. `apply` applies the given function to a value. The value to apply comes from a `Probe`, and `apply` is called twice.

```swift
// FunctionType.swift — function type
func triple(_ n: Int) -> Int { n * 3 }
func apply(_ transform: (Int) -> Int, to value: Int) -> Int {
    transform(value)
}
let typeProbe = Probe("function-type")
let transform = triple
print(type(of: transform))
print(typeProbe.use { apply(transform, to: typeProbe.eval(4)) })
print(typeProbe.use { apply(transform, to: typeProbe.eval(5)) })
typeProbe.report()
```

```
@Sendable (Int) -> Int
12
15
function-type: 2 evaluations, 2 uses -> on-every-use
```

`type(of: transform)` printed `@Sendable (Int) -> Int`: besides the parameter and return types, the type carries a `@Sendable` attribute, because top-level functions can be shared safely in concurrent environments. In reading, the `(Int) -> Int` part is the decisive one. `apply` gave `12` and `15` in two calls: `4 * 3` and `5 * 3`. The `Probe` showed two evaluations; in each call the argument was computed once, before `apply` ran. The `transform` constant itself was not counted as an evaluation, because assigning a function to a constant does not run it.

When you carry a function as a value, the moment of calling stays with you: when you call it, how many times and with which argument is clear at the call site.

Once you have learned to read a function type, the signatures in the standard library become readable too. The `map` method of an array expects an `(Element) -> T` function; you can give it a named function or a closure. The closure you will see in the next lesson is a function value without a name and obeys the same type rules.

The `@Sendable` attribute at the start of the type can be ignored for now; you will see it with concurrency in later topics. What matters is knowing that a function is carried as a value and does not run until the call parentheses arrive. Assigning the same function to two different variables does not produce two separate copies; both point to the same function.

What is computed before the call is the argument, not the function value; the two evaluations of the measurement confirm this.

**LB51.** The function type was measured with a function that has one parameter; functions with several parameters and functions that return functions are outside this lesson.

#### The Limiting Measurement

A default value comes into play when the caller does not give one. When the caller gives an argument, the opposite holds: that expression is evaluated before the call, whether the function body reads it or not. This is an ordinary rule for the language, but before the measurement shows it, an intuition lingers: the argument of a parameter that is not read seems never to be evaluated. The body below never reads its parameter, and the helper function `marked` shows with `print` when the argument ran.

```swift
// main.swift — the argument is evaluated before the body
func marked(_ n: Int) -> Int {
    print("argument \(n)")
    return n
}

func ignore(_ value: Int) -> String {
    print("body ran")
    return "did not read"
}

let argumentProbe = Probe("argument-expression")
_ = argumentProbe.use { ignore(argumentProbe.eval(marked(7))) }
_ = argumentProbe.use { ignore(argumentProbe.eval(marked(8))) }

let allProbes = [argumentProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
argument 7
body ran
argument 8
body ran
argument-expression: 2 evaluations, 2 uses -> on-every-use
immediately: 0
on-first-use: 0
on-every-use: 1
never: 0
```

The line `argument 7` was printed before the line `body ran`, even though the body never used the `value` parameter. `argument-expression` was evaluated twice in two calls: the argument is computed every time, before the function is called. The difference from the default expression is this: a default expression runs only when no argument is given, while a given argument always runs.

**LB52.** The fact that the `ignore` body does not read the parameter does not measure whether the compiler eliminates the argument expression; the `argument 7` line in the output is the only evidence of this measurement and holds only for this construct.

#### Summary

- The argument label makes the call readable; the `_` label removes it, and `= value` defines a default argument.
- A tuple returns several values; an `inout` parameter changes the caller's `var` variable through `&`.
- The default argument expression is evaluated on every call in which no argument is given.
- If an argument is given, the default expression is never evaluated; a given argument is evaluated before the call even if the body does not read it.
- The moment of this lesson: **on every use** (the default argument expression).

#### Next Step

A function can take another function as a parameter, and you can write it as an expression without a name. When does the body of this expression run, and at which moment does it see the variables around it? The next lesson looks at closures.

### Closures

Source: https://academia.sh/en/courses/swift/closures

Introduces closure syntax, the `$0` shorthand, the trailing closure and the `sorted(by:)` call; measures that a capture list is evaluated once, when the closure is created.

Functions are named behavior. A closure writes the same behavior without a name, and you can put it in a variable or give it to another function. The question of this lesson has two parts: when does the body of a closure run, and at which moment does the closure see the variables around it?

#### Writing a Closure

The longest form writes the parameter and return types inside the curly braces: `{ (a: Int, b: Int) -> Bool in a < b }`. The `in` keyword separates the signature from the body. When the type can be inferred from the context the signature drops, and the parameters are reached by position: `$0` is the first and `$1` the second argument. If the body is a single expression, `return` is not written and the value of the expression is returned implicitly.

If the last parameter of a function is a closure, the closure can be written outside the parentheses. This is called a trailing closure. If no other argument is left inside the parentheses, the parentheses themselves drop too: `numbers.sorted { $0 > $1 }`. `sorted(by:)` sorts an array according to the comparison closure you give.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The measurement block first runs these forms: the long closure, the short closure with `$0`, `map` and our own `apply`. Then it builds two closures. `scale` carries a `Probe` in its body and is called twice; `unused` is built in the same way but is never called.

```swift
// main.swift — closure forms and the moment of the body
let numbers = [3, 1, 2]
print(numbers.sorted(by: { (a: Int, b: Int) -> Bool in a < b }))
print(numbers.sorted { $0 > $1 })
print(numbers.map { $0 * 2 })

func apply(_ n: Int, using transform: (Int) -> Int) -> Int { transform(n) }
print(apply(4) { $0 + 1 })

let bodyProbe = Probe("closure-body")
let unusedProbe = Probe("uncalled-body")

let scale = { (n: Int) -> Int in bodyProbe.eval(n * 2) }
let unused = { (n: Int) -> Int in unusedProbe.eval(n) }

print(bodyProbe.use { scale(1) })
print(bodyProbe.use { scale(2) })
_ = unusedProbe.use { unused }
_ = unusedProbe.use { unused }

let allProbes = [bodyProbe, unusedProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
[1, 2, 3]
[3, 2, 1]
[6, 2, 4]
5
2
4
closure-body: 2 evaluations, 2 uses -> on-every-use
uncalled-body: 0 evaluations, 2 uses -> never
immediately: 0
on-first-use: 0
on-every-use: 1
never: 1
```

`sorted(by:)` gave the result from smallest to largest, and with `$0 > $1` from largest to smallest. `map` doubled every element, and `apply(4)` with a trailing closure returned 5. The measurement lines look at the body of the closure: `closure-body` was evaluated twice in two calls, that is, the body runs again on every call and the moment is `on-every-use`. `uncalled-body` showed zero evaluations in two uses: building a closure does not run the body, the body runs only when there is a call.

**LB53.** How many times the comparison closure of `sorted(by:)` is called was not counted in this lesson; the number depends on the sorting algorithm, and the lesson shows only the result.

**LB54.** The closure body was measured with a simple expression that returns only an `Int` and has no side effects; escaping closures are outside this lesson.

#### Escaping Closure: Stored Work

If you give a closure to a function and the function stores the closure after it has finished, the type of the closure has to be marked with `@escaping`. This mark says the closure may escape from the call. A non-escaping closure (the default) disappears when the call ends. An escaping closure can be added to an array, assigned to a property and called later. The line that builds the closure does not do the work; the work is done when the closure is called.

The block below writes a queue class. `add` stores the closure, and `runAll` calls all the stored ones. The body of the closure writes to a `Probe`. The number of evaluations is printed after the closures are added to the queue and after they are run.

```swift
// Queue.swift — a stored closure
final class Queue {
    var jobs: [() -> Int] = []
    func add(_ job: @escaping () -> Int) {
        jobs.append(job)
    }
    func runAll() {
        for job in jobs { _ = job() }
    }
}
let queueProbe = Probe("stored-job")
let queue = Queue()
queue.add { queueProbe.eval(1) }
queue.add { queueProbe.eval(2) }
print(queueProbe.evaluations)
_ = queueProbe.use { queue.runAll() }
_ = queueProbe.use { queue.runAll() }
print(queueProbe.evaluations)
queueProbe.report()
```

```
0
4
stored-job: 4 evaluations, 2 uses -> on-every-use
```

When the two closures were added to the queue the counter was 0: adding did not run the body. After the two `runAll` calls the counter became 4, because in each call two closures ran. The closures were stored and evaluated their body again every time they were called; so the moment reads `on-every-use`.

An escaping closure is the way to postpone work. You read when the body will run not from the line that builds the closure, but from the line that calls it.

**LB55.** Stored closures were measured inside a class; the consequences of capturing `self` in an escaping closure are outside this lesson.

#### Shorthand Argument Names

You can give the closure parameters names like `$0` and `$1`. This spares you from writing the parameter list when the type is inferred from the context. If the body is a single expression, the implicit return works too. The operators of the standard library can also be passed like a function: writing `numbers.sorted(by: >)` does the same job as `numbers.sorted { $0 > $1 }`. `reduce` takes a closure with two parameters, and these parameters become `$0` and `$1`.

The block below runs three shorthand forms on an array. `map` passes every element through a `Probe`, and a second `map` call is applied this time to four elements.

```swift
// Shorthand.swift — shorthand arguments
let mapProbe = Probe("map-body")
let numbers = [3, 1, 2]
print(numbers.sorted(by: >))
print(numbers.reduce(0) { $0 + $1 })
print(mapProbe.use { numbers.map { mapProbe.eval($0 * 10) } })
print(mapProbe.use { (numbers + [4]).map { mapProbe.eval($0 * 10) } })
mapProbe.report()
```

```
[3, 2, 1]
6
[30, 10, 20]
[30, 10, 20, 40]
map-body: 7 evaluations, 2 uses -> on-every-use
```

`sorted(by: >)` gave `[3, 2, 1]`. `reduce` computed the sum as 6. The two `map` calls produced the arrays `[30, 10, 20]` and `[30, 10, 20, 40]`. The `Probe` showed seven evaluations: three in the first call and four in the second. The closure body ran once for every element. So the moment reads `on-every-use`.

Shorthand names are readable when the body is short; when the body grows, a named parameter keeps the meaning. Besides `$0` and `$1`, passing the operator directly is the shortest form, but it works only when the signature of the operator matches the signature of the closure.

**LB56.** Shorthand names were measured with an `Int` array; `$2` and beyond, and the meaning of `$0` in nested closures, are outside this lesson.

#### A Closure Can Change the Variable It Captures

If the captured variable is a `var`, the closure does not only read it, it can change it. The closure holds not a copy of the variable but the variable itself. If several closures capture the same variable, a change made by one closure changes the value the other sees. For this reason captured `var` variables behave like shared state, and the lifetime of the variable extends together with the closures that capture it.

The block below captures a `hits` counter with two closures. `record` increases the counter by one and passes the value through a `Probe`; `skip` increases the counter by two directly. The closures are called in the order `record`, `skip`, `record`.

```swift
// Shared.swift — a shared captured variable
let sharedProbe = Probe("shared-counter")
var hits = 0
let record = {
    hits += 1
    return sharedProbe.eval(hits)
}
let skip = { hits += 2 }
print(sharedProbe.use { record() })
skip()
print(sharedProbe.use { record() })
print(hits)
sharedProbe.report()
```

```
1
4
4
shared-counter: 2 evaluations, 2 uses -> on-every-use
```

`record` returned 1 on the first call, and 4 on the second call after `skip` had made the counter 3; the last read confirmed that the value of `hits` is 4. The two closures saw the same variable: `record` saw the change `skip` made on the second call. Two calls brought two evaluations, and the moment is `on-every-use`.

Shared state gives flexibility, but makes it harder to follow which closure changed the variable and when. When the state is small and close by this is no problem; as it grows, putting the state inside a type becomes more readable.

**LB57.** The shared state was measured on an `Int`; closures running concurrently and accessing the same variable are outside this lesson.

#### Trailing Closure Syntax

If the last parameter of a function is a closure, you can write the closure outside the parentheses. `perform(times: 2) { ... }` and `perform(times: 2, action: { ... })` are the same call. If the only argument of the function is the closure, the parentheses can drop altogether. This syntax only shortens the writing; when the closure runs does not change. The closure runs when the function calls it, and it runs as many times as the function calls it.

The block below writes a function: `perform` calls the given closure as many times as asked. The closure body writes to a `Probe`. The function is called first with two, then with three repetitions.

```swift
// Trailing.swift — trailing closure
func perform(times: Int, action: () -> Void) {
    for _ in 0..<times { action() }
}
let trailingProbe = Probe("trailing-closure")
trailingProbe.use { perform(times: 2) { _ = trailingProbe.eval(1) } }
trailingProbe.use { perform(times: 3) { _ = trailingProbe.eval(1) } }
print(trailingProbe.evaluations)
trailingProbe.report()
```

```
5
trailing-closure: 5 evaluations, 2 uses -> on-every-use
```

`perform(times: 2)` ran two times and `perform(times: 3)` three times; the total was five evaluations. Writing the closure outside the parentheses did not change the number of runs: the value of `times` decided how many times the closure would be called. On each call the body was evaluated again, and the moment reads `on-every-use`.

This syntax helps only with reading. When the closure is last among the parameters, the call looks like a control-flow statement: `perform(times: 3) { ... }` reads like a loop. But the rule behind it is the same: a closure is a value, and the function calls it as many times as it wants.

**LB58.** The trailing closure was measured with a closure that has no return value; the syntax of several trailing closures is outside this lesson.

#### A Capture List Freezes the Value

When a closure captures a `var` variable from its surroundings it holds the variable itself; changes made to the variable later are reflected in the closure. If you want to change this, you write a capture list at the start of the closure: `{ [snapshot = count] in snapshot }`. The list takes a copy of the value of `count` at the moment the closure is created, and the closure now uses that. Even if `count` changes later, the number the closure sees stays the same.

The block below captures the same variable with two closures: one does not use a list, one does. After the closures are created the variable is changed and both are called. The value read passes through a `Probe`.

```swift
// CaptureList.swift — capture list
let listProbe = Probe("capture-list")
var count = 1
let live = { listProbe.eval(count) }
let frozen = { [snapshot = count] in listProbe.eval(snapshot) }
count = 5
print(listProbe.use { live() }, listProbe.use { frozen() })
listProbe.report()
```

```
5 1
capture-list: 2 evaluations, 2 uses -> on-every-use
```

The `live` closure gave `5`, the `frozen` closure `1`. Because `live` holds the variable itself, it saw the new value after the assignment `count = 5`. `frozen`, on the other hand, took a copy of the value of `count` at the moment it was created, under the name `snapshot`; changing the variable later did not reach it. Two calls brought two evaluations, and the moment is `on-every-use`.

The capture list is the way to write explicitly which value the closure will see. If you want a value to stay as it was when the closure was created, you write it in the list; if you want the closure to see the values the variable takes later, you do not use a list at all.

You can also write several items in a capture list; each item takes its own copy at the moment the closure is created.

**LB59.** The capture list was measured with an `Int` variable; capturing class instances weakly is outside this lesson and is covered in a later topic.

#### The Limiting Measurement

If a closure uses a variable from its surroundings, it captures it. In capturing without a list, the closure is bound to the variable itself: if the variable changes later, the closure sees the new value on every call. A capture list is written inside square brackets and takes a value while the closure is being created: `{ [snapshot = level] in snapshot }`. The expression in the list is evaluated once while the closure is being built, and is not evaluated again at the calls. The measurement below builds two closures with the same variable, changes the variable and calls both of them twice.

```swift
// main.swift — capture list
let captureProbe = Probe("capture-list")

var level = 1
let plain = { level }
let listed = { [snapshot = captureProbe.eval(level)] in snapshot }
level = 5

print(captureProbe.use { plain() }, captureProbe.use { listed() })
print(captureProbe.use { plain() }, captureProbe.use { listed() })

let allProbes = [captureProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
5 1
5 1
capture-list: 1 evaluations, 4 uses -> immediately
immediately: 1
on-first-use: 0
on-every-use: 0
never: 0
```

The `plain` closure saw 5 because it stayed bound to the `level` variable; the `listed` closure carried the value 1 it had when it was built. The expression in the capture list was evaluated once, while the closure was being built and before the four uses: the `capture-list` line gives `immediately`. The body running on every call and the capture list running once are two separate moments of the same closure.

**LB60.** `level` is a `var`, and the measurement shows only the capture of a value-type variable; capturing class instances was not measured in this lesson.

**LB61.** That a capture list runs once while the closure is built was measured with a single closure; that in code which builds the same closure in several places each build is a separate evaluation is outside this lesson.

#### Summary

- A closure is unnamed behavior; `$0` and `$1` reach the arguments by position, and a single-expression body does not need `return`.
- If the last parameter is a closure, the closure can be written outside the parentheses (a trailing closure).
- A closure body runs on every call; the body of a closure that is never called never runs.
- A capture list is evaluated once while the closure is built; a later change to a variable captured without a list is visible at the call.
- The moment of this lesson: **on every use** (the closure body).

#### Next Step

The examples in this topic used an expression like `values.min() ?? 0`: `min()` cannot return a value for an empty array. Swift carries this situation in the type as the absence of a value. The first lesson of the next topic, Optional Values, introduces this idea.

## The Type System

Optionals as the expression of absence in the type, and safe unwrapping; value and reference semantics with structures and classes; enumerations; stored, computed and observed properties; protocols, extensions, generics, error handling and access control.

### Optionals

Source: https://academia.sh/en/courses/swift/optionals

Measuring how absence is expressed in the type, why a transforming closure never runs on nil, and where absence stops in nested layers.

The previous lesson measured closures and capture lists. A closure's body runs where it is called, not where it is written, and a closure that is never called never has its body evaluated. This lesson asks the same question through a method that takes a closure as a parameter and sometimes never calls it. That method belongs to the most heavily used part of the type system: the type that carries absence as a value.

Most languages express absence with a special value, such as a null pointer or a magic number, and leave it to the programmer to check for that value everywhere. Swift writes absence into the type itself. An **optional** is a box that either holds a value or holds nothing, and it is written `Int?`. An `Int` is always an integer; an `Int?` may or may not be one. The compiler does not let the two types stand in for each other, so the check for absence cannot be forgotten by accident; skipping it takes a force unwrap, written on purpose.

The course's measuring axis does not change in this lesson either: **when is this expression evaluated?** There are four moments: immediately, on first use, on every use, never. The `Probe` class, which counts by the rule, is given below exactly as it is. This lesson concentrates on the fourth moment: an expression that is never evaluated.

#### The Core

Every lesson uses the same core. `Probe` counts how many times an expression is evaluated (`eval`) and how many times it is used (`use`); the `moment` property derives the moment from those two numbers. In the binding measurement of the opening lesson, the distribution over eight expressions was 2/1/3/2: two immediately, one on first use, three on every use, two never. In this lesson we measure only our own slice.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

#### Absence as a Type

Before looking at what is inside an optional, we look at the optional itself first. `Int("42")` converts a string to an integer, and because the conversion can fail, the return type is `Int?`. If it succeeds the box is filled; in a call like `Int("x")` the box is empty and its value is `nil`.

```swift
// main.swift — an optional is an enumeration
func describe(_ value: Int?) -> String {
    switch value {
    case .some(let number):
        return "filled \(number)"
    case .none:
        return "empty"
    }
}

let parsed = Int("42")
let broken = Int("x")
print(type(of: parsed))
print(describe(parsed))
print(describe(broken))
print(parsed == .some(42), broken == .none)
print(broken == nil)
```

```
Optional<Int>
filled 42
empty
true true
true
```

The first line gives the name of the type: `Int?` is only shorthand, and the real type is `Optional<Int>`. `Optional` is an **enumeration** defined in the standard library, and it has two cases: `.some`, which carries a value, and `.none`, which carries nothing. That is why the `describe` function can open the box with a `switch`; each case gets its own branch, and in the `.some` branch the carried value is bound to the name `number`. The fourth line shows that the value `42` equals `.some(42)` and that the empty box equals `.none`; the fifth line shows that writing `nil` is shorthand for `.none`.

A second conclusion follows from the same output: `Int?` and `Int` are two separate types. The fragments below do not compile; each was first run in a temporary measured block, and the compiler rejected both. They appear here for explanation only.

```swift
let a: Int? = 5
let b = a + 1   // does not compile: Int? and Int cannot be added
let c: Int = nil   // does not compile: nil can only be assigned to an optional type
```

The addition on the first line sees the box itself, not the number inside it, and the compiler asks for the box to be opened. The assignment on the second line tries to write absence into an `Int`. The only place that can carry absence is one whose type is marked with `?`. How the box is opened is the subject of the next lesson; in this lesson we will measure two methods that work with the box without opening it.

#### Where Absence Comes From

Optionals do not enter a program only through string conversion. The standard library returns an optional in many places where absence is ordinary, though not everywhere: an array index out of bounds does not produce `nil`, it stops the program. A key that is not in a dictionary has no value; an empty array has no first element. In these cases there is no need to expect a special error value or an exception: the return type already says "maybe".

```swift
// main.swift — the standard library reports absence with an optional
let ages = ["ada": 36, "alan": 41]
let names: [String] = []
print(ages["ada"], ages["grace"])
print(names.first, [3, 1, 2].first)
print(ages["ada"] == 36, ages["grace"] == nil)
```

```
Optional(36) nil
nil Optional(3)
true true
```

On the first line, the value of the existing key arrives as `Optional(36)`; in other words, even `36` is not a plain `Int` but a box with `36` inside. The missing key gives `nil`. The second line shows the same pattern for arrays: the `first` property of the empty array is `nil`, while the `first` property of the non-empty array returns a boxed `3`. On the third line, the box is compared with an unboxed number: the `==` operator automatically boxes the `36` on the right so that both sides are `Int?`. That is why `ages["ada"] == 36` compiles, while the `+` example above does not, because it needs the value inside the box.

These sources make one distinction visible: the reason for the absence is not written in the optional's type. `ages["grace"]` is empty because the key does not exist, and `Int("x")` is empty because the string is not a number, but both are the same `nil`. When the reason is needed, error handling comes into play; that topic arrives later in this course. When the reason does not matter, an optional is the tool with the least overhead.

#### map on nil

Since `Optional` is a two-case box, a method that transforms the value inside the box behaves differently in the two cases. `map` takes a **transforming closure**. If the box is filled, the closure is called with the value inside and the result is put in a new box; if the box is empty, the closure is not called and the result is an empty box. We measure it with two boxes, one filled and one empty, each used twice, and the body of the transforming closure marked with `eval`.

```swift
// main.swift — map on nil does not call the transformer
let filled = Probe("map-filled")
let vacant = Probe("map-empty")
let present: Int? = Int("21")
let missing: Int? = Int("twenty one")

for _ in 1...2 {
    _ = filled.use { present.map { filled.eval($0 * 2) } }
    _ = vacant.use { missing.map { vacant.eval($0 * 2) } }
}
filled.report()
vacant.report()
```

```
map-filled: 2 evaluations, 2 uses -> on-every-use
map-empty: 0 evaluations, 2 uses -> never
```

On the filled box, `map` runs the transformer again every time it is called: two uses, two evaluations, the moment is **on every use**. Notice that the result is not stored anywhere; the expression inside `use` runs from scratch each time. On the empty box there are two uses but no evaluations, because `map` returns as soon as it sees the box is empty, without ever reaching the transformer. The expression `filled.eval($0 * 2)` or `vacant.eval($0 * 2)` written in the body stays in the source, but on the empty box it is never evaluated. The rule names this case **never**.

This measurement shows once more when a closure's body runs: a closure does not run where it is written, and the method that is expected to call it does not always call it. An error, a side effect or an expensive computation inside a transformer that is never called never happens. Code that relies on the transformer's side effect misses that side effect on an empty box.

**TS1.** This measurement is for `map` only; the behavior of other methods such as `filter`, `compactMap` or `forEach` on an empty box was not tried. Cases where the transformer is written as a pure computation rather than with a side effect were not measured separately either.

##### Two maps in a Chain

If an empty box comes out of one `map` call empty, a second `map` added after it meets the same box. When the first link of the chain produces nothing, the later links find no value to work on. We measure this with two transformers; the body of each transformer is tied to its own `Probe`, and the chain is built from scratch on every use.

```swift
// main.swift — on an empty box every map in the chain is skipped
let stageOne = Probe("chain-first")
let stageTwo = Probe("chain-second")
let seed: Int? = Int("ten")

for _ in 1...2 {
    _ = stageOne.use { seed.map { stageOne.eval($0 + 1) }.map { stageTwo.eval($0 * 2) } }
    _ = stageTwo.use { seed.map { stageOne.eval($0 + 1) }.map { stageTwo.eval($0 * 2) } }
}
stageOne.report()
stageTwo.report()
```

```
chain-first: 0 evaluations, 2 uses -> never
chain-second: 0 evaluations, 2 uses -> never
```

Neither transformer was ever evaluated. The second not running might have been expected, since its own input is the result of the first; the first not running comes from the box being empty in the first place. The `seed` value is built with `Int("ten")`, so it is `nil`; the first `map` passes the empty box through without transforming it, and the second `map` receives the same empty box. That is why, in a long chain of transformers, an absence at the very start runs none of the later links.

**TS2.** In this chain only the starting value is empty; the case where a transformer in the middle of the chain returns `nil` is not in this measurement, and the behavior of the following `map` there was not measured separately.

#### map and flatMap

The transformer itself can also return an optional. `Int($0)`, which converts a string to an integer, is exactly such an expression: its result is `Int?`. `map` puts the transformer's result as it is into a new box, so a box goes inside a box. `flatMap` flattens the box the transformer returns out to the outside. The difference shows with three inputs: a valid string, an invalid string and an empty box.

```swift
// main.swift — map produces nested layers, flatMap flattens
let inputs: [String?] = ["7", "x", nil]
for input in inputs {
    let nested = input.map { Int($0) }
    let flat = input.flatMap { Int($0) }
    print(nested, flat)
}
```

```
Optional(Optional(7)) Optional(7)
Optional(nil) nil
nil nil
```

On the first line `map` gives a two-layer result and `flatMap` a single-layer one. The second line shows the real difference: `"x"` is an invalid string and the `map` result is `Optional(nil)`, meaning the outer box is filled and the inner box is empty; `flatMap` gives `nil` directly. On the third line the input itself is empty, so both methods never reach the transformer and `nil` comes back.

The second line is the ground for the next measurement. `Optional(nil)` and `nil` are different values, and both express absence; but one carries the absence one layer inside, the other at the very outside. Which layer it stops at decides whether the next method will call its transformer.

**TS3.** This output is for the `Int` conversion only; cases where the transformer converts to another type or throws an error were not tried. The `Optional(...)` notation in the output is the `print` format of this version; what is measured is the number of layers, not the format itself.

#### The Bounding Measurement

At the start of the lesson we set a rule for `map`: on an empty box the transformer does not run. The rule is right, but which box counts as empty is a question of layers. The type `Int??` is a two-layer box. While the outer box is filled, the box inside can be empty; this case is written `.some(nil)`. Below are two values: one whose outer layer is filled but whose inside is empty, and one that is empty at the very outside. `map` is applied to both, and the transformer returns whether the value it received is `nil`.

```swift
// main.swift — if the outer layer is filled, map runs even when the absence is inside
let outer = Probe("outer-filled")
let hollow = Probe("outer-empty")
let inner: Int?? = .some(nil)
let empty: Int?? = nil

for _ in 1...2 {
    _ = outer.use { inner.map { value in outer.eval(value == nil) } }
    _ = hollow.use { empty.map { value in hollow.eval(value == nil) } }
}
outer.report()
hollow.report()
print(inner.map { $0 == nil })
print(empty.map { $0 == nil })
```

```
outer-filled: 2 evaluations, 2 uses -> on-every-use
outer-empty: 0 evaluations, 2 uses -> never
Optional(true)
nil
```

On the value whose outer layer is filled, the transformer ran and received `nil`: the result is `Optional(true)`, because the transformer returned the inner absence as `true`. On the value that is empty at the very outside, the transformer never ran. So for `map`, absence is only the outermost box being empty; a value that carries absence inside but is filled outside is, as far as `map` is concerned, filled.

This result narrows the area in which the lesson's rule holds. A transforming closure never being evaluated depends on the **outer layer** of the box being empty. When working with nested optionals, `map` does not carry absence "one layer up": it hands the absence in the inner layer to the transformer as a value. That is why the `Optional(nil)` result in the previous section is a filled box for a later `map` call. When the number of layers is to be reduced, `flatMap` is used.

**TS4.** This measurement is for a two-layer box; boxes with three or more layers were not tried. We observed that the transformer received `nil` through the `value == nil` comparison; no other way of observing it was tried.

#### Summary

- `Int?` and `Int` are separate types; absence is carried inside the type, and the compiler makes the check mandatory.
- Optional is an enumeration: `.some` carries a value, `.none` (that is, `nil`) carries no value.
- On an empty box `map` never calls the transforming closure; on a filled box it runs it again on every call.
- When the transformer returns an optional, `map` adds a layer and `flatMap` flattens; `Optional(nil)` and `nil` are different values.
- In an `Int??` whose outer layer is filled, `map` runs the transformer even though absence is inside.
- This lesson's moment: **never**. On an empty box, the `map` transformer is never evaluated.

#### Next Step

In this lesson we worked without opening the box: `map` and `flatMap` transformed the value but left the result in a box again. When a real value is needed, the box has to be opened. The next lesson measures the ways of opening it: when `if let` and `guard let` evaluate their right-hand side, at which candidate a `??` chain stops, and what optional chaining does to the rest of the chain when it sees `nil`.

### Unwrapping Optionals

Source: https://academia.sh/en/courses/swift/unwrapping-optionals

Measuring when the right-hand side of if let and guard let, a ?? chain and optional chaining are evaluated.

The previous lesson worked without opening the box: `map` and `flatMap` never ran the transformer on an empty box and ran it on every call on a filled one, and the result was a box again. Somewhere in a program a real value is needed: a number to print, the name of a file, a term in a sum. This lesson lists the ways of opening the box and asks the same question of each: when is the unwrapped expression evaluated, and when does the code after unwrapping run?

Swift offers several different tools for opening a box, and this lesson measures five. **Optional binding**, that is `if let` and `guard let`, opens the box once and binds its content to a name. The `??` operator puts a fallback value in place of an empty box. **Optional chaining**, written `?.`, makes a call only if the box is filled. Force unwrapping, the postfix operator written with an exclamation mark, turns absence into a runtime error. The fifth, `map` and `flatMap`, was measured in the previous lesson. Each tool evaluates at a different moment, and the difference decides where error handling has to be written.

The course's measuring axis does not change here either: **when is this expression evaluated?** There are four moments: immediately, on first use, on every use, never. The `Probe` class, which counts by the rule, is given below exactly as it is.

#### The Core

Every lesson uses the same core. `Probe` counts how many times an expression is evaluated (`eval`) and how many times it is used (`use`); the `moment` property derives the moment from those two numbers. In the binding measurement of the opening lesson, the distribution over eight expressions was 2/1/3/2: two immediately, one on first use, three on every use, two never. In this lesson we measure only our own slice.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The measurements need a small class whose name can be changed. The class is not a measurement itself, it only supplies material for the chaining example, so it has no output.

```swift
// User.swift — a small class whose name can be changed
final class User {
    var name: String
    var renames = 0

    init(name: String) {
        self.name = name
    }

    func rename(_ newName: String) {
        name = newName
        renames += 1
    }
}
```

#### Optional Binding

In `if let number = lookup("12", probe: source)`, the right-hand side of the equals sign is an optional. Swift evaluates it once, checks the result, binds the content to `number` if the box is filled, and runs the body of the block. If the box is empty, the body never runs. In the measurement below the right-hand side is wrapped in `source.eval`, and the bound name is used twice in the body.

```swift
// main.swift — if let evaluates its right side once, the bound name is used twice
let source = Probe("if-let-rhs")

func lookup(_ text: String, probe: Probe) -> Int? {
    probe.eval(Int(text))
}

if let number = lookup("12", probe: source) {
    _ = source.use { number + 1 }
    _ = source.use { number * 2 }
}
source.report()
```

```
if-let-rhs: 1 evaluations, 2 uses -> immediately
```

One evaluation, two uses, moment **immediately**. The right-hand side ran before the block was entered; once the name is bound, `number` is an ordinary integer, and using it does not run the right-hand side again. This is a contrast with `map` from the previous lesson: `map` ran the transformer on every call, whereas optional binding runs the expression once and keeps the result in the name. If we want to read the same right-hand side twice later, the bound name needs no extra evaluation.

The bound name is valid only inside the block; when the block ends, `number` does not exist. Writing the same function call again inside a second `if let` means a second evaluation, because `if let` runs its right-hand side at the moment of binding and shares the result with no other `if let`. When a value is needed in several places, the call has to be written once and its result kept in a name.

**TS5.** This measurement is for an `if let` whose right-hand side is a single function call. The form that joins several conditions with commas (`if let a, let b`) and the `where` condition were not measured.

#### guard let and the Short Form

`guard let` does the same binding from the opposite direction. If the box is empty, the `else` block runs, and that block must leave the scope (`return`, `throw`, `break`, `continue`, or a call that never returns such as `fatalError`); if the box is filled, the name is bound and stays valid after the `guard` line, for the rest of the function. That is why checks that need an early exit are written with `guard`: the real work stays unindented and the error case is collected at the top. The short form, `if let maybe`, binds under the same name without writing it again.

```swift
// main.swift — guard let and the short if let
func label(for text: String) -> String {
    guard let number = Int(text) else {
        return "invalid"
    }
    return "number \(number)"
}

let maybe: Int? = Int("5")
if let maybe {
    print("short form", maybe)
}
print(label(for: "30"))
print(label(for: "thirty"))
```

```
short form 5
number 30
invalid
```

The first line shows the short form: the optional named `maybe` is used inside the block under the same name, as a non-optional integer. The second and third lines show the two paths of `label(for:)`, which contains the `guard let`: `"30"` passes the binding and the string at the end of the function is built, while `"thirty"` returns from the `else` branch. The bound `number` is an `Int` after the `guard` line; there is no need to open the box again.

The difference between the two binding forms lies in how the weight is distributed, not in a measurable difference in evaluation. `if let` keeps the success path in a block, `guard let` keeps the failure path in a block. Choosing the form that leaves the longer path unindented gives the more readable result.

#### The Fallback Value: ??

The `??` operator has two sides. If the optional on the left is filled, its content is the result; if it is empty, the fallback on the right is the result. The expression on the right is a parameter written as an **autoclosure**: Swift wraps it in a closure, and the operator calls it only when needed. This is another example of the transformer from the previous lesson: an expression written in the source may never run until a method calls it.

When written as a chain, this behavior goes one step further. Below there are three candidates: an empty box, a filled box marked with the `second` probe, and a fallback number marked with the `third` probe. The chain stops at the first filled candidate. The loop runs two rounds, and each round uses the result twice.

```swift
// main.swift — a ?? chain stops at the first filled value
let second = Probe("second-candidate")
let third = Probe("third-candidate")
let nothing: Int? = nil
let found: Int? = 8

for _ in 1...2 {
    let result = nothing ?? second.eval(found) ?? third.eval(0)
    _ = second.use { result }
    _ = third.use { result }
}
second.report()
third.report()
```

```
second-candidate: 2 evaluations, 2 uses -> on-every-use
third-candidate: 0 evaluations, 2 uses -> never
```

The second candidate was evaluated in every round: two rounds, two evaluations, moment **on every use**. The third candidate was never evaluated, because the second was filled and the chain was cut there. So when `a ?? b ?? c` is written, `c` is computed only if both `a` and `b` are empty. Putting an expensive fallback on the right therefore creates no wasted work: as long as an earlier candidate is filled, that expression is never evaluated.

This behavior has a side consequence. A side effect in the expression on the right, such as a counter increment or a log line, happens only when the box on the left is empty. Code that wants the side effect to happen in every case should write it before the `??` expression, not inside it.

**TS6.** This measurement is for a chain of three candidates with a filled second candidate fixed. The two-candidate form with a filled left box and the case where the fallback is a function call were not measured separately.

#### Optional Chaining

The `?` in `presentUser?.rename("y")` is a question mark and it marks an absence check. If the receiver is filled, the call is made; if the receiver is empty, the call is not made and the value of the expression is `nil`. If the call returned `Int`, chaining would turn it into `Int?`; so the result of chaining is always an optional, and even a call with no return type gives `Void?`.

The real question is the call's argument. When `absentUser?.rename(skipped.eval("x"))` is written, the receiver is empty and the call is not made. The argument expression is something computed before the call; so is it computed when the receiver is empty? We measure with two receivers, one empty and one filled. For each, the argument is a probe marked with `eval`, and the loop runs two rounds.

```swift
// main.swift — when the chain stops at nil, the argument is not evaluated either
let skipped = Probe("nil-receiver")
let reached = Probe("filled-receiver")
let absentUser: User? = nil
let presentUser: User? = User(name: "ada")

for _ in 1...2 {
    absentUser?.rename(skipped.eval("x"))
    presentUser?.rename(reached.eval("y"))
    _ = skipped.use { absentUser?.renames }
    _ = reached.use { presentUser?.renames }
}
skipped.report()
reached.report()
print(presentUser?.name ?? "none", presentUser?.renames ?? -1)
```

```
nil-receiver: 0 evaluations, 2 uses -> never
filled-receiver: 2 evaluations, 2 uses -> on-every-use
y 2
```

With the empty receiver, the argument was never evaluated. The moment chaining sees that the receiver is empty, it skips the rest of the expression, and the argument is part of that rest. With the filled receiver, the argument was evaluated once in every round. The last line confirms the result: the filled user's name became `y`, and two renames were counted over two rounds.

This behavior is expected to hold in longer chains as well: when `a?.b?.c(expensive())` is written and `a` or `b` is empty, `expensive()` must not run; this lesson measured only a chain of two links (TS8). Putting a call with a side effect in an argument to the right of a link that may come back empty makes that side effect conditional.

#### Combining the Tools

The five tools are rarely used alone. The last output line above shows two tools together: in `presentUser?.name ?? "none"`, chaining opens the box and reads the name, and because the result is a box again, `??` puts a fallback string in the case where it stays empty. Since the receiver is filled the output was `y`; if the receiver were empty, `none` would have been printed. In the same way, `presentUser?.renames ?? -1` gives the counter value and returns `-1` for an empty receiver.

The evaluation moment of a combination comes from the moments of its parts. Because chaining skips the rest on an empty receiver, `??` looks only once at the box that the chain returns. The fallback sits on the right and is never evaluated as long as the left side is filled. These two rules complement each other: absence is handled in one place only, and after that point the code works with a non-optional value.

**TS7.** This combination is for the case of two tools side by side only, and it was read from the last line of the output. Forms where three or more tools are nested were not measured separately.

#### The Bounding Measurement

The rule we built for chaining is this: on an empty receiver the argument is never evaluated. In the previous measurement the receiver was directly a constant and was empty from the start. So what happens if the absence appears in the middle of the chain, as the result of a method call? Below, the `find` method always returns `nil`. One expression calls `find("ada")?.rename(...)` on an empty box; the second element on the same line is not part of the chain but a separate expression.

```swift
// main.swift — a link that comes back empty mid-chain skips the argument of the next call
struct Directory {
    func find(_ name: String) -> User? {
        nil
    }
}

let tail = Probe("middle-empty-next")
let free = Probe("middle-empty-independent")
let directory = Directory()

for _ in 1...2 {
    _ = (directory.find("ada")?.rename(tail.eval("z")), free.eval("w"))
    _ = tail.use { 0 }
    _ = free.use { 0 }
}
tail.report()
free.report()
```

```
middle-empty-next: 0 evaluations, 2 uses -> never
middle-empty-independent: 2 evaluations, 2 uses -> on-every-use
```

Absence born in the middle of the chain also skipped the argument of the next call: when `find` returned empty, the `rename` call was not made and its argument was never evaluated. The independent expression in the second element on the same line, separated by a comma, was evaluated in every round. What is skipped is the chain itself, the part after the `?`; being written on the same line does not make an expression part of the chain.

This result narrows the area where the lesson's rule holds. The sentence "an empty receiver does not evaluate the argument" applies to the expressions that come after the link that stays empty, and in the two links measured it did not depend on where the absence was born. Expressions outside the chain are not within the scope of this rule.

**TS8.** This measurement is for a chain of two links. The behavior of a `?` in the middle of chains of three or more links, and the case where the receiver is a property, were not measured separately.

#### Force Unwrapping

Force unwrapping is not measured in this lesson, because there is no evaluation moment to measure: if the box is filled the value inside is taken, and if it is empty the program stops. The fragment below compiles but gives a runtime error when run; since it makes no output claim, it stands here only as source.

```swift
let text = "thirty"
let broken = Int(text)!   // crashes at runtime: the box is empty
print(broken)
```

Force unwrapping moves an absence check from compile time to runtime. The guarantee the compiler gives through the type system is lifted here: a value of type `Int?` is used as an `Int` on the author's word that "this box is filled". If the word is not kept, the program stops. Force unwrapping can be defended where absence is provably impossible, for example in converting a text that is written as a constant in the source and known to be valid; it cannot be defended on data that comes from a user or from outside.

#### Summary

- `if let` evaluates its right-hand side once and before entering the block; the bound name causes no further computation.
- `guard let` writes the same binding with an early exit; the bound name is valid after the `guard` line.
- A `??` chain stops at the first filled candidate; a candidate on the right is computed only if the one on the left is empty.
- Optional chaining on an empty receiver skips the call to the right of the `?` and its argument.
- Force unwrapping moves the absence check to runtime and carries no moment to measure.
- This lesson's moment: **immediately**. The right-hand side of `if let` is evaluated once, before the block is entered.

#### Next Step

In this lesson the boxes were opened and the values inside were used. The values themselves are defined in one of two ways: as copied structures or as shared classes. The next lesson looks at the difference between structures and classes by measuring at exactly which moment the copy is made.

### Structures and Classes

Source: https://academia.sh/en/courses/swift/structures-and-classes

Measuring copying on assignment for structures, sharing for classes, when a default value is built, and why a copy appears at the first mutation.

The previous lesson measured the ways of opening a box and listed when each one evaluates its expression. The value that comes out may be an `Int` or a `String`, but the real data of a program is usually a type that keeps several fields together: a point, an order, a document. Swift has two basic forms for such types (enumerations and actors are the subject of other lessons). A **structure** is a **value type**: its content is copied when it is assigned. A **class** is a **reference type**: assigning it gives a second name to the same object.

Most books explain this difference with the question "who sees what": does one name see the change made through the other? This lesson asks a different question: when does the copy appear? Does the assignment itself produce a copy, or does the copy appear only at the first mutation? The course's measuring axis splits this question into four moments: immediately, on first use, on every use, never. The `Probe` class is given below exactly as it is.

#### The Core

Every lesson uses the same core. `Probe` counts how many times an expression is evaluated (`eval`) and how many times it is used (`use`); the `moment` property derives the moment from those two numbers. In the binding measurement of the opening lesson, the distribution over eight expressions was 2/1/3/2: two immediately, one on first use, three on every use, two never. In this lesson we measure only our own slice.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The first measurements below use three types. `Point` is a structure that holds two integers, and `Counter` is a class that holds a single counter. `Order` is a structure with a field that has a default value; the default value is a function call, and when the function runs it prints a line. This block has no output, because it only defines the types.

```swift
// Types.swift — a structure, a class and a structure with a default value
struct Point {
    var x: Int
    var y: Int
}

final class Counter {
    var value = 0
}

func makeNote() -> String {
    print("default value built")
    return "none"
}

struct Order {
    var id: Int
    var note = makeNote()
}
```

#### Assignment: Copy or Share

We write the same two lines with a structure and with a class. With the structure, after `var second = first` and `second.x = 10`, `first` does not change. With the class, after `let right = left` and `right.value = 5`, the two names are bound to the same object and both see `5`.

```swift
// main.swift — a structure is copied on assignment, a class is shared
let first = Point(x: 1, y: 2)
var second = first
second.x = 10
print(first.x, second.x)

let left = Counter()
let right = left
right.value = 5
print(left.value, right.value)
```

```
1 10
5 5
```

The first line shows the structure: `first.x` stayed `1` and `second.x` became `10`. The assignment gave an independent copy. The second line shows the class: `left.value` and `right.value` are both `5`, because there is a single `Counter` object and two names are bound to it. Notice that `right` is a `let` constant and the `value` inside the object could still change: `let` forbids binding the name to another object, not changing the content of the bound object. With a structure, `let` means the whole value is immutable: a field of an immutable structure cannot be assigned, even if the field is declared with `var`.

The output separates the two types but does not say when the copy appears. The sentence "a structure is copied on assignment" exists in textbooks as a model; what we measure is observable behavior: after the change, the two values are independent. Whether the copy physically appears at assignment or later is measured below.

**TS9.** This measurement is for a structure with two integer fields and a class with a single field. Structures whose fields hold a reference to another class, and the copying of class fields inside a structure, are not part of this measurement.

#### Passing to a Function

Assignment is only one face of the value and reference distinction; the same distinction shows up when an argument is passed to a function. When a function takes a structure as a parameter, it works with its own copy: a change made inside does not reach the caller's value. With a class parameter, the function and the caller look at the same object. In the measurement below, `moved` changes and returns a copy of the structure, while `bump` changes the counter in place.

```swift
// main.swift — a structure passed to a function is copied, a class is shared
func moved(_ point: Point) -> Point {
    var copy = point
    copy.x += 100
    return copy
}

func bump(_ counter: Counter) {
    counter.value += 100
}

let origin = Point(x: 1, y: 2)
let shifted = moved(origin)
print(origin.x, shifted.x)

let ticker = Counter()
bump(ticker)
print(ticker.value)
```

```
1 101
100
```

On the first line `origin.x` stayed `1` and `shifted.x` became `101`: `copy` inside `moved` was a separate value and the change was written only to it. On the second line `ticker.value` became `100`, because `bump` changed the same `Counter` object, and the function returns nothing. So the signature of a function whose parameter is a structure tells the reader "this function does not change the value I call it with", as long as the structure holds only values and the parameter is not `inout`. The signature of a function with a class parameter gives no such guarantee; you have to look at the body.

The practical result of this distinction shows in debugging. If a structure's value changed unexpectedly, the change was made in the scope of that value itself; if a class object changed unexpectedly, every place that can reach the object is a suspect. Using value types between function signatures narrows the field of suspects.

**TS10.** This measurement is for one structure parameter and one class parameter. Passing with an `inout` parameter, and a structure captured by a closure, are not part of this measurement.

#### The Default Value: Once per Instance

The `note` field of the `Order` structure starts with the result of the `makeNote()` function. This default value is not built once and shared among all instances; every `Order` instance builds its own default value. Moreover, the value is not computed at all if the caller supplies the field itself. We measure with three orders: two with the default note and one with an explicit note.

```swift
// main.swift — the default is evaluated per instance, but only when not given
let o1 = Order(id: 1)
let o2 = Order(id: 2)
let o3 = Order(id: 3, note: "urgent")
print(o1.note, o2.note, o3.note)
```

```
default value built
default value built
none none urgent
```

`makeNote()` ran twice, for two of the three orders. For the third order, which gave the note explicitly, the function was never called. Both places where it ran appear before the print line; that is, the default value was computed on the calling line, while the instance was being built.

One result follows: every expression written as a default value is evaluated as many times as there are instances, minus the number of supplied values. If an expensive expression is written as a default value, that cost is paid on every instance. The Properties lesson measures deferring this cost with `lazy`.

**TS11.** This measurement was made with three instances and one field with a default value. The evaluation order of several fields with default values, and the same case in classes, were not measured separately.

#### Copy-on-Write

When a large value type is assigned, copying all of it for real would be wasteful. Some types of the standard library therefore use a technique called **copy-on-write**: assignment only adds a second reference to a storage, and the copy appears only when the shared storage has to be changed, at the first mutation. We can build the same technique by hand in our own type. The `Document` structure keeps its text in a `Storage` class. `append` first asks with `isKnownUniquelyReferenced` whether we are the only owner of the storage; if not, it copies the storage and reports the moment of copying through the `onCopy` closure.

```swift
// Document.swift — a structure boxed in a class, copying on write
final class Storage {
    var text: String

    init(text: String) {
        self.text = text
    }
}

struct Document {
    private var storage: Storage
    private let onCopy: () -> Void

    init(text: String, onCopy: @escaping () -> Void) {
        storage = Storage(text: text)
        self.onCopy = onCopy
    }

    var text: String {
        storage.text
    }

    mutating func append(_ more: String) {
        if !isKnownUniquelyReferenced(&storage) {
            onCopy()
            storage = Storage(text: storage.text)
        }
        storage.text += more
    }
}

final class Holder {
    var document: Document

    init(_ document: Document) {
        self.document = document
    }
}
```

Look at the code closely. The `storage` field is `private`, so it is invisible from outside; only the read-only `text` property is exposed. Changes pass only through `append`, which is marked `mutating`, and the decision to copy is made only there. This narrowing matters: because the copying rule stays in one place, no other method of the type can change the storage while it is shared. The `onCopy` closure is there for the measurement; production code would not contain such a notification, but here it lets us count in exactly which call the copy appears. The `Holder` class will be used in the last measurement: it makes a `Document` value the field of a class object.

This block has no output; it only defines `Document` and the `Holder` that wraps it in a class. Now we make the assignment `duplicate = original`, change both, and measure exactly when the copy appears. The `onCopy` closure is wrapped in `cow.eval`; `append` is called twice.

```swift
// main.swift — the copy appears at the first mutation, not at assignment
let cow = Probe("copy-on-write")
let original = Document(text: "ab", onCopy: { _ = cow.eval(()) })
var duplicate = original

_ = cow.use { duplicate.append("c") }
_ = cow.use { duplicate.append("d") }
cow.report()
print(original.text, duplicate.text)
```

```
copy-on-write: 1 evaluations, 2 uses -> on-first-use
ab abcd
```

The assignment itself produced no copy: the evaluation count is one and the moment is **on first use**. The first `append` was sharing the storage with another value, so the copy appeared at that moment. The second `append` was the sole owner of the copied storage, so no copy was needed. The last line confirms the result: `original` is still `ab`, while `duplicate` is `abcd`. There are two values, but only one copy took place, and it took place not at assignment but at the first mutation.

We also write out what the numbers mean. One evaluation says the copy appeared once; two uses say two `append` calls were made. If the evaluation count were equal to the use count, every change would give birth to a copy and the moment would be **on every use**. If it were zero, no change would have needed a copy and the moment would be **never**. The measured one is below two and it appeared at the first use; these three numbers together decide the moment.

This measurement answers the question we asked at the start. In a value type like `Document`, which shares its storage, the copy appears after assignment, during the first write. For the reading side there is no difference; the cost of the copy falls on the first writer. The choice between a value type and a reference type can therefore be read not only as a semantic preference but also as a question of when the cost is paid.

**TS12.** This measurement is only for the `Document` type we built by hand; the copy-on-write behavior of the standard library's array, dictionary and string types was not measured in this lesson.

#### The Bounding Measurement

The rule we built for copy-on-write is this: the copy appears at the first mutation. The rule has a condition, the storage must be shared with another owner. This condition does not hold in two cases. In the first, nobody has become a co-owner of the `solo` document; in the second, the document is inside a class and two names are bound to the same class object, that is, there is no second `Document` value sharing the storage. In both, `append` is called twice.

```swift
// main.swift — a single-owner document, or one shared inside a class, is not copied
let unique = Probe("single-owner")
var solo = Document(text: "ab", onCopy: { _ = unique.eval(()) })
_ = unique.use { solo.append("c") }
_ = unique.use { solo.append("d") }

let shared = Probe("class-sharing")
let holder = Holder(Document(text: "ab", onCopy: { _ = shared.eval(()) }))
let alias = holder
_ = shared.use { holder.document.append("c") }
_ = shared.use { alias.document.append("d") }

unique.report()
shared.report()
print(solo.text, holder.document.text, alias.document.text)
```

```
single-owner: 0 evaluations, 2 uses -> never
class-sharing: 0 evaluations, 2 uses -> never
abcd abcd abcd
```

In both cases `onCopy` was never called: the moment is **never**. The single-owner document was not copied even at the first mutation, because there was no second owner to share with. The document inside the class was not copied either: since `holder` and `alias` are bound to the same `Holder` object, an append made through one name is visible through the other, and a second copy of the `Document` value never appears. The last line confirms this sharing: all three names print `abcd`.

This limit narrows the lesson's rule. The sentence "a value type is copied on assignment" and the sentence that completes it, "the copy appears at the first mutation", hold only if there are two separate values sharing the storage. If a value type is the field of a class, the reference semantics of the class wins: no copy appears, because the class object is already single.

**TS13.** This measurement is for a single class object and two names. The case where the class object itself, together with its `Document` field, is assigned to another value, or where two different `Holder` objects carry the same document, was not measured.

#### Summary

- A structure gives an independent copy on assignment; when a class is assigned, two names are bound to the same object.
- A class name declared with `let` does not make the object immutable; a structure declared with `let` makes the whole value immutable.
- A default value is evaluated once per instance, and never if the caller supplies the field.
- With copy-on-write the copy appears not at assignment but at the first mutation, and only if the storage is shared.
- With a single-owner value, or one shared inside a class, the copy never appears.
- This lesson's moment: **on first use**. In a copy-on-write document the copy appears at the first mutation.

#### Next Step

In this lesson we measured whether a type is a value or a reference and when the copy appears. Some types are not a list of fields but a choice among several distinct states: a measurement is either in degrees or a label. The next lesson measures enumerations, which describe those states and the values carried along with each of them.

### Enumerations

Source: https://academia.sh/en/courses/swift/enumerations

Measuring when a raw value and an associated value are set up, how pattern matching opens them, and why a computed property runs on every read.

The previous lesson measured types that are lists of fields: structures and classes always carry the same fields. Some data, however, calls not for a list of fields but for being in one of several distinct states. A day of the week is one of seven values; a measurement is either a number in degrees or a label. These two examples describe different things, but both are expressed with an **enumeration**.

A Swift enumeration is more powerful than its counterpart in many languages. Each `case` is not only a name; depending on its definition it can have a **raw value**, or an **associated value** that travels with the case. Enumerations can also carry computed properties and methods; they cannot carry stored instance properties. The lesson first measures when these two kinds of value are set up, and then when a computation inside an enumeration runs. The course's measuring axis does not change: **when is this expression evaluated?** There are four moments: immediately, on first use, on every use, never. The `Probe` class is given below exactly as it is.

#### The Core

Every lesson uses the same core. `Probe` counts how many times an expression is evaluated (`eval`) and how many times it is used (`use`); the `moment` property derives the moment from those two numbers. In the binding measurement of the opening lesson, the distribution over eight expressions was 2/1/3/2: two immediately, one on first use, three on every use, two never. In this lesson we measure only our own slice.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

The measurements use two enumerations. `Weekday` has an `Int` raw value and lists all its cases through `CaseIterable`; when the first case is given `1`, the following ones become `2` and `3`. `Reading` carries a value with its cases: `celsius` takes a `Double`, `label` takes a `String`. This block has no output, because it only defines the types.

```swift
// Types.swift — enumerations with raw values and with associated values
enum Weekday: Int, CaseIterable {
    case monday = 1, tuesday, wednesday
}

enum Reading {
    case celsius(Double)
    case label(String)
}
```

#### Raw Values

A raw value is the counterpart assigned to a case as a constant at compile time. The raw value of each case must be different, and the values are written in the definition. When `1` is written for the first case, the values of the following cases are determined by adding one each time. The raw value is reached through the `rawValue` property, and to go the other way, from a raw value to a case, the form `Weekday(rawValue: 3)` is used. It is clear that the reverse direction cannot find a case for every raw value; this form therefore returns an optional.

```swift
// main.swift — raw value, construction with rawValue, and allCases
print(Weekday.tuesday.rawValue)
print(Weekday(rawValue: 3) == .wednesday)
print(Weekday(rawValue: 9) == nil)
print(Weekday.allCases.count)
```

```
2
true
true
3
```

The first line gives the raw value of the `tuesday` case: because the first case started at `1`, it is `2`. The second line shows that the value constructed with `rawValue: 3` equals `.wednesday`. The third line shows that for `9`, which is the raw value of no case, the result is `nil`; the empty box we saw in the first lesson is here the result of searching for a case, not of an `Int` conversion. The fourth line shows that `allCases`, added by `CaseIterable`, counts three cases.

Here the raw value is a tool for identity and conversion. It is used to convert an integer coming from a network response, a file or a database field safely into a case, and it forces the caller to decide what to do with an invalid value.

A raw value does not have to be an integer. In an enumeration whose type is `String`, the raw value of each case is the case's own name, unless written explicitly. We do the same three operations with a list of planets: reading the raw value, constructing a case from a raw value, and trying to construct from an invalid raw value.

```swift
// main.swift — a String raw value is the case name unless specified
enum Planet: String {
    case mercury, venus, earth
}

print(Planet.venus.rawValue)
print(Planet(rawValue: "earth") == .earth)
print(Planet(rawValue: "pluto") == nil)
```

```
venus
true
true
```

The first line shows that the raw value of the `venus` case is `"venus"` although no value was written. The second line shows that the raw value `"earth"` gives the `.earth` case, and the third line shows that for `"pluto"`, which is not in the list, the result is `nil`. As in the integer example, the reverse direction returned an optional here too: the path from a raw value to a case always carries the possibility of absence.

**TS14.** These measurements are for one enumeration with an `Int` raw value and one with a `String` raw value. Other raw value types (`Double`, `Character`) and the behavior of `Int` cases with raw values written for only some of them were not measured separately.

#### Associated Values and Pattern Matching

An associated value works differently from a raw value. A raw value is fixed at definition and is the same in every instance of the same case. An associated value is determined when the case is **constructed**, and each instance carries its own value. `Reading.celsius(21.5)` and `Reading.celsius(30.0)` are the same case but carry different data. To reach what is inside such a value, **pattern matching** with `switch` is used: in the branch of each case, the associated value is bound to a name.

```swift
// main.swift — opening an associated value with pattern matching
let readings = [Reading.celsius(21.5), Reading.label("hot")]
for reading in readings {
    switch reading {
    case .celsius(let degrees):
        print("degrees", degrees)
    case .label(let text):
        print("label", text)
    }
}
```

```
degrees 21.5
label hot
```

The two `Reading` values in the array enter the `switch` in turn. The first selects the `celsius` branch and binds the `21.5` inside it to the name `degrees`; the second selects the `label` branch and binds the string `"hot"` to the name `text`. In each branch the bound name is valid only in the body of that branch, and its type is the type of that case's associated value. The compiler checks that all cases are handled: if a case is skipped, the `switch` is considered incomplete, and a branch for the missing case or a `default` has to be written.

This behavior is the same pattern as the optional of the first lesson. `Optional` is also an enumeration, and its `.some` case carries an associated value; `if let` and `case .some(let value)` inside a `switch` are two spellings of the same matching. This lesson gives a second example of why the box in that lesson behaves the way it does.

When only a single case has to be looked at, writing a `switch` is heavy. `if case` writes the same matching as a single condition: if the case matches, the associated value is bound and the block runs; if it does not match, the `else` branch runs. One more condition can be added with a comma; after the associated value is bound, it is used in that condition.

```swift
// main.swift — looking at a single case with if case
let current = Reading.celsius(18.0)
if case .celsius(let degrees) = current, degrees < 20 {
    print("cool", degrees)
}
if case .label(let text) = current {
    print("label", text)
} else {
    print("not a label")
}
```

```
cool 18.0
not a label
```

The first `if case` matched `current` with the `celsius` case, bound `18.0` to the name `degrees`, and also passed the `degrees < 20` condition after the comma. The second `if case` tried to match the same value with the `label` case, and because there was no match it ran the `else` branch. This is the same behavior as `switch`: when a case does not match, the associated value is never bound and the related name is not in scope.

**TS15.** This measurement is for an enumeration with two cases, each with a single associated value. Cases with several associated values, `indirect` enumerations and branches with a `where` condition were not measured.

#### When the Associated Value Is Set Up

An associated value is an expression given when the case is constructed. When `Reading.celsius(stamp.eval(19.0))` is written, the expression `stamp.eval(19.0)` is evaluated once while the case is constructed, and the result is stored inside the case. When it is later read with `switch`, the expression is not computed again; what is read is the value stored in the case. We measure this by reading twice.

```swift
// main.swift — the associated value is evaluated once, when the case is constructed
let stamp = Probe("associated-value")
let reading = Reading.celsius(stamp.eval(19.0))

for _ in 1...2 {
    _ = stamp.use { () -> Double in
        switch reading {
        case .celsius(let degrees):
            return degrees
        case .label:
            return -1
        }
    }
}
stamp.report()
```

```
associated-value: 1 evaluations, 2 uses -> immediately
```

One evaluation, two uses, moment **immediately**. The evaluation took place on the line where `reading` was constructed, before the `use` calls. Both `switch` statements read the same stored value and did not run the expression again. This differs from the raw value: the expression of a raw value never runs, because it is a constant. The expression of an associated value runs once per instance.

The practical result the measurement shows is this: an expensive computation written into an associated value is paid when the case is constructed, and reads need no extra computation. Code that wants the computation done at the moment of reading should use a computed property, not an associated value. The next section measures that property.

**TS16.** This measurement is for an expression that wraps a constant `Double` literal. Cases where the associated value is a function call, or an expression containing another associated value, were not measured separately.

#### The Bounding Measurement

A raw value and an associated value are fixed when the case is constructed or in the definition; that is, reading them costs nothing. An enumeration, however, can carry a **computed property** as well as stored values. This property stores no value; it runs its body every time it is read. In the `Sensor` enumeration, the `fahrenheit` property converts the Celsius degrees, carried as an associated value, to Fahrenheit on every read. The conversion expression is marked with a `Probe`, and the property is read twice.

```swift
// main.swift — an enumeration's computed property runs on every read
enum Sensor {
    case reading(Probe, Double)

    var fahrenheit: Double {
        switch self {
        case .reading(let probe, let celsius):
            return probe.eval(celsius * 9 / 5 + 32)
        }
    }
}

let derived = Probe("computed-property-sensor")
let sensor = Sensor.reading(derived, 20)
_ = derived.use { sensor.fahrenheit }
_ = derived.use { sensor.fahrenheit }
derived.report()
print(sensor.fahrenheit)
```

```
computed-property-sensor: 2 evaluations, 2 uses -> on-every-use
68.0
```

Two reads, two evaluations, moment **on every use**. A computed property does not store its result; each time `sensor.fahrenheit` is written, its body runs from the start. The associated value `20` was fixed at construction, but the `68.0` derived from it is computed again on every read. The second line of the output shows that the next read of the same property gives the same result.

This result narrows the lesson's rule. The sentence "an associated value is evaluated once when the case is constructed" is true only for the associated value itself. Every computed property derived from an associated value runs from the start on every read. When the same computation is needed in several places, keeping the result in a name is cheaper than reading the computed property again everywhere.

There is also a limit for raw values, and it cannot be measured, because it does not compile. A raw value must be a constant written in the source. The fragment below tries to assign the return of a function as a raw value and does not compile: the compiler rejects it. The error message said that a raw value has to be written as a constant. The fragment stands here only for explanation.

```swift
func rawOf() -> Int { 3 }
enum Bad: Int {
    case a = 1
    case b = rawOf()   // does not compile: a raw value must be a constant
}
```

This limit shows a second difference between the two kinds of value. An associated value can be any expression evaluated at runtime; a raw value is a constant known at compile time. The expression of a raw value is therefore never evaluated at runtime.

**TS17.** This measurement is for a single computed property derived from two stored values. A computed property that is not read-only (one with a `set`) and the methods of the enumeration were not measured separately. In the rejected raw value fragment only a function call was tried; other forms of expression were not tried.

#### Reading the Three Values Together

Three different kinds of value were measured in this lesson, and each fell on a different moment. A raw value is a constant written in the definition; as an expression it never runs at runtime, so no measuring probe can be attached to it. An associated value is an expression given when the case is constructed and is evaluated once per instance; in the measurement this moment came out **immediately**. A computed property stores no value and runs its body on every read; in the measurement this moment came out **on every use**.

Although the three kinds may look interchangeable, they answer different questions. If a code coming from outside has to be converted into a case, a raw value fits, because the reverse direction returns an optional and makes invalid input visible. If instance-specific data has to be carried next to a case, an associated value fits, because different instances of a case can carry different data. If a result derived from the carried data has to be produced at the moment it is needed, a computed property fits, but the price paid on every read has to be counted too.

#### Summary

- A raw value is fixed in the definition, and `Weekday(rawValue:)` returns an optional; a value that is not found gives `nil`.
- Pattern matching with `switch` binds the associated value to a name in each branch and checks that all cases are handled.
- An associated value is evaluated once when the case is constructed; reads do not run the expression again.
- A computed property in an enumeration stores no result and runs again on every read.
- A raw value must be a constant known at compile time; a function call cannot be a raw value.
- This lesson's moment: **immediately**. The expression of an associated value is evaluated on the line where the case is constructed.

#### Next Step

In this lesson we saw that a property in an enumeration runs on every read. Properties do not belong to enumerations alone: structures and classes also carry stored, computed and observed properties, and there is `lazy`, which defers an expression to the first read. The next lesson measures these kinds of property and when each of them sets up its value.

### Properties

Source: https://academia.sh/en/courses/swift/properties

Measuring when stored, computed and observed properties, lazy properties and static let values are set up.

The previous lesson showed that the associated value of an enumeration is evaluated once, when the case is constructed, and that its computed property is evaluated on every read. The same distinction is not special to enumerations. The **properties** of structures, classes and enumerations name the data of a type, and each property sets up its value at its own time: some while the instance is created, some on every read, some on the first read.

This lesson measures four kinds of property. A **stored property** keeps a value inside the instance. A **computed property** stores no value and runs an expression when read. An **observed property** is a stored property that runs its `willSet` and `didSet` **property observers** before and after it changes. A **lazy property** does not set up its value until the first read. The course's measuring axis is the same in this lesson: **when is this expression evaluated?** There are four moments: immediately, on first use, on every use, never. The `Probe` class is given below exactly as it is.

#### The Core

Every lesson uses the same core. `Probe` counts how many times an expression is evaluated (`eval`) and how many times it is used (`use`); the `moment` property derives the moment from those two numbers. In the binding measurement of the opening lesson, the distribution over eight expressions was 2/1/3/2: two immediately, one on first use, three on every use, two never. In this lesson we measure only our own slice.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

#### Three Basic Kinds

The first measurement puts stored, computed and observed properties side by side. In the `Rectangle` structure `width` and `height` are stored properties, and `area` is a computed one: it holds no value and does the multiplication on every read. `target` in the `Thermostat` class is a stored property that carries `willSet` and `didSet` observers. `willSet` sees the upcoming value under the name `newValue` before the value is written, and `didSet` sees the old value under the name `oldValue` after it is written.

```swift
// main.swift — stored, computed and observed property
struct Rectangle {
    var width: Int
    var height: Int

    var area: Int {
        width * height
    }
}

final class Thermostat {
    var target = 20 {
        willSet { print("willSet", target, "->", newValue) }
        didSet { print("didSet", oldValue, "->", target) }
    }

    init(target: Int) {
        self.target = target
    }
}

let rect = Rectangle(width: 3, height: 4)
print(rect.area)
let thermostat = Thermostat(target: 18)
print("initializer done")
thermostat.target = 22
thermostat.target = 25
```

```
12
initializer done
willSet 18 -> 22
didSet 18 -> 22
willSet 22 -> 25
didSet 22 -> 25
```

The first line gives the `3 * 4` result of the `area` property. Before the second line, the initializer had written `18` into the `target` field, but the observers did not run: no line appeared until the initializer finished. Observers run only on assignments made after the instance is fully set up; an assignment in the type's own initializer does not trigger them. The next two assignments ran the observers, and for each assignment the order was `willSet`, the assignment, `didSet`. In the `willSet` output the right-hand value shows the upcoming value, and in the `didSet` output the left-hand value shows the old value; in the second, since `target` is already updated, the old value could not have been reached without the name `oldValue`.

The three kinds answer three different questions. A stored property answers "where does the value sit?". A computed property answers "how is the value derived from other values?". An observed property answers "what should happen when the value changes?". None of them is lazy: the stored value is set up at construction, the computed value on every read, and the observer on every write.

**TS18.** This measurement is for a computed property in a structure and an observed property in a class. Observers in structures, the direction of change of a computed property, and the behavior of observers on a property passed with `inout` were not measured separately.

#### Computed Properties and set

A computed property is not only read, it can be written too. For this, a `set` is written next to the `get`; `set` takes the assigned value under the name `newValue` and is obliged to reflect it into the stored properties. In the `Temperature` structure, `fahrenheit` neither stores a value nor is a source itself. When read it is derived from `celsius`, and when written it updates `celsius`.

```swift
// main.swift — a computed property tied to a stored field with get and set
struct Temperature {
    var celsius: Double

    var fahrenheit: Double {
        get { celsius * 9 / 5 + 32 }
        set { celsius = (newValue - 32) * 5 / 9 }
    }
}

var reading = Temperature(celsius: 100)
print(reading.fahrenheit)
reading.fahrenheit = 32
print(reading.celsius)
```

```
212.0
0.0
```

With `celsius` at `100`, reading `fahrenheit` gave `212.0`. Then `32` was written to `fahrenheit` and the `set` block pulled `celsius` to `0.0`. A single piece of data can be read and written in two different representations, and the real value sits in one place, the `celsius` field. This is the strength of a computed property: it offers two forms of the same information without causing inconsistency.

The same result follows from the enumeration example in the previous lesson: a computed property runs again on every read. The difference here is that with `set` it also works in the opposite direction.

#### Lazy Properties

Some properties are expensive and not needed in every instance. Computing them while the instance is created is wasted work for an instance that will never be read. The `lazy` keyword leaves the property unset until the first read. The first read evaluates the expression once and stores the result inside the property, and later reads give the stored value. The `summary` property in the `Report` class computes the total of the rows lazily.

```swift
// main.swift — a lazy property is evaluated once, on the first read
final class Report {
    let probe: Probe
    var rows = [1, 2, 3]
    lazy var summary: Int = probe.eval(rows.reduce(0, +))

    init(probe: Probe) {
        self.probe = probe
    }
}

let summaryProbe = Probe("lazy-first-read")
let report = Report(probe: summaryProbe)
_ = summaryProbe.use { report.summary }
_ = summaryProbe.use { report.summary }
summaryProbe.report()
```

```
lazy-first-read: 1 evaluations, 2 uses -> on-first-use
```

One evaluation, two reads, moment **on first use**. The computation was done at the first read and the second read gave the stored result. This is what separates it from a computed property: a computed property would have made two evaluations in two reads. `lazy` is not a computed property, it is a deferred stored property. That is why `lazy` has to be a `var`; because the first read writes the value into the property, a writable stored property is needed.

#### The Difference Between a Default Value and lazy

In the previous lesson we measured that a default value is evaluated once per instance. Now we write the same expression in two forms so the difference becomes visible. The `Ticket` class carries two properties: `eagerId` calls the same `makeId` function through a default value, and `lazyId` calls it through `lazy`, and the function prints a line every time it is called. Two tickets are created, and then only the first ticket's `lazyId` property is read twice.

```swift
// main.swift — a default value runs at creation, lazy at the first read
func makeId(_ kind: String) -> Int {
    print("built", kind)
    return 7
}

final class Ticket {
    var eagerId = makeId("eager")
    lazy var lazyId = makeId("lazy")
}

let tickets = [Ticket(), Ticket()]
print("created")
print(tickets[0].lazyId)
print(tickets[0].lazyId)
```

```
built eager
built eager
created
built lazy
7
7
```

The first two lines show that the `eagerId` property of both tickets was set up before `created` was printed: each instance computed its own default value at creation time. For `lazyId` there are no such lines. The `lazy` line appeared only when `tickets[0].lazyId` was first read, and it appeared only once; the second read gave `7` from the stored value. The `lazyId` property of the second ticket was never read, so it was never set up.

The difference is summarized briefly. The expression of a default value runs for every instance, while the instance is being created. A `lazy` expression runs only for the instances that are read, at the first read. If twenty tickets are created and only one's id is looked at, `lazy` does one computation instead of twenty.

#### static let

Values that belong to the type, that is `static` properties, are bound not to instances but to the type itself. A value defined with `static let` is lazy: it is set up on first access, and set up once. `Config.version` is built with a closure, and the closure prints a line each time it runs.

```swift
// main.swift — static let is set up on first access
enum Config {
    static let version: String = {
        print("static let built")
        return "1.0"
    }()
}

print("before")
print(Config.version)
print(Config.version)
```

```
before
static let built
1.0
1.0
```

The `before` line was printed before the first access; the `static let built` line appeared only when `Config.version` was first read, and it appeared only once. The later read gave the value `1.0` from the stored copy. This is the same behavior as `lazy`, but there is one difference: `static let` is not tied to an instance, and unlike `lazy` it does not have to be a `var`, so it can be used as an immutable lazy constant.

**TS19.** This measurement is for a `static let` set up with a closure. `static var` and `static` computed properties were not measured separately.

#### The Bounding Measurement

The rule we built for the `lazy` property is this: the expression is evaluated once, on the first read. This rule holds for a class instance, because a class instance is a single shared object. We move the same property into a structure. Structures are copied on assignment, and a copy carries its own copy of a `lazy` property that has not been read yet. In the `Sheet` structure, `total` is a lazy property; `sheetA` is copied and both copies are read once.

```swift
// main.swift — a lazy property in a structure multiplies with the copy
struct Sheet {
    let probe: Probe
    var rows = [1, 2, 3]
    lazy var total: Int = probe.eval(rows.reduce(0, +))
}

let sheetProbe = Probe("struct-lazy-copy")
var sheetA = Sheet(probe: sheetProbe)
var sheetB = sheetA
_ = sheetProbe.use { sheetA.total }
_ = sheetProbe.use { sheetB.total }
sheetProbe.report()
```

```
struct-lazy-copy: 2 evaluations, 2 uses -> on-every-use
```

Two reads, two evaluations, moment **on every use**. Both copies set up the same `lazy` property separately, because the property had not been set up yet at the moment of copying, and each copy received its own unset property. The same value was computed twice.

This result narrows the lesson's rule. The word "once" holds for one instance. In a structure there are as many instances as copies, and a `lazy` property that has not yet been read is set up independently in each copy at its first read. In a class this situation does not arise, because no copy appears.

A `lazy` property in a structure has a second limit, and it too cannot be measured, because it does not compile. Reading writes to the property, so it requires the structure to be mutable. The fragment below reads the `lazy` property of a structure defined with `let` and does not compile: the compiler rejects it. The error message said that a mutating read cannot be used on a structure defined with `let`. The fragment stands here only for explanation.

```swift
struct Sheet2 {
    var rows = [1, 2, 3]
    lazy var total: Int = rows.reduce(0, +)
}
let fixed = Sheet2()
print(fixed.total)   // does not compile: a lazy property cannot be read on a let structure
```

This is a side consequence of the `lazy` property: the read includes a write. A structure instance meant to be read has to be a `var`. A class does not have the same restriction, because a class name defined with `let` fixes only the name, not the content of the object.

**TS20.** This measurement is for two copies and a single `lazy` property. Nested structures, cases where a `lazy` property depends on another `lazy` property, and, in the rejected fragment, only a `let` structure were tried; other ways of fixing a value were not tried.

#### Summary

- A stored property is set up at construction, a computed property on every read, and an observer on every write; an assignment in the type's own initializer does not trigger observers.
- A computed property can be written with `set` and reflects the real value into another stored property.
- A `lazy` property is evaluated once, on the first read; a default value runs for every instance during creation.
- `static let` is set up on first access, and set up once.
- A not-yet-read `lazy` property in a structure multiplies with the copy; it cannot be read on a `let` structure.
- This lesson's moment: **on first use**. A `lazy` property is evaluated once, on the first read.

#### Next Step

In this lesson we measured when properties set up their value. Types do not only carry data, they can also promise behavior. The next lesson measures protocols: the contracts that say which properties and methods a type must provide, and the moment at which a property is evaluated when it is called from code that uses the contract.

### Protocols

Source: https://academia.sh/en/courses/swift/protocols

Measures when a value that fulfills a protocol requirement is evaluated: a default implementation runs on every call, but the conforming type decides the moment.

The previous lesson measured properties: a stored property is evaluated on the line where it is defined, a computed property runs again on every read, and a `lazy` property waits until the first read. Now we move to the question of who writes a property. A type can carry a property in order to follow a contract set by another type, and the contract itself can supply a body. How these two cases affect the moment is the subject of this lesson.

A **protocol** is a list of the members a type has to carry: properties, methods, initializers, subscripts and associated types. Each item on the list is a **requirement**. It carries a name, a type and whether it is readable or writable, but it carries no body. A type that conforms to the protocol fulfills the requirement with its own body. In a protocol's **extension**, though, a **default implementation** can be written for a requirement; if the conforming type does not give its own body, the default runs. Extensions get their own treatment in lesson 07; here we use only protocol extensions.

#### The Measurement Setup

Every lesson starts with the same helper. `Probe` counts how many times an expression is evaluated and how many times it is used; `moment` derives the moment from those two numbers.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

**TS21.** Every observation, apart from `never`, carries two uses; the numbers come from two calls on a single type, and because a protocol is not a value itself, what is measured is always an instance of a conforming type.

#### A Property in a Protocol Extension

The protocol below sets two requirements: a name and a `Probe`. `greeting`, on the other hand, is a computed property written in the protocol's extension; no conforming type defines it. Two types, `Person` and `Robot`, use the same default implementation.

```swift
// main.swift — a property in a protocol extension runs on every call
protocol Describable {
    var name: String { get }
    var tracker: Probe { get }
}

extension Describable {
    var greeting: String { tracker.eval("hello \(name)") }
}

struct Person: Describable {
    let name: String
    let tracker: Probe
}

struct Robot: Describable {
    let name: String
    let tracker: Probe
}

func makeRobot(_ tracker: Probe) -> some Describable {
    Robot(name: "Rex", tracker: tracker)
}

func twice<T: Describable>(_ value: T) -> Int {
    value.greeting.count + value.greeting.count
}

let direct = Probe("default-implementation")
let existential = Probe("any-protocol-type")
let opaque = Probe("some-protocol-type")
let generic = Probe("generic-function")

let ada = Person(name: "Ada", tracker: direct)
_ = direct.use { ada.greeting }
_ = direct.use { ada.greeting }

let crowd: [any Describable] = [Person(name: "Can", tracker: existential)]
_ = existential.use { crowd[0].greeting }
_ = existential.use { crowd[0].greeting }

let made = makeRobot(opaque)
_ = opaque.use { made.greeting }
_ = opaque.use { made.greeting }

_ = generic.use { twice(Person(name: "Eda", tracker: generic)) }
_ = generic.use { twice(Person(name: "Eda", tracker: generic)) }

let all = [direct, existential, opaque, generic]
for probe in all { probe.report() }
tally(all)
```

```
default-implementation: 2 evaluations, 2 uses -> on-every-use
any-protocol-type: 2 evaluations, 2 uses -> on-every-use
some-protocol-type: 2 evaluations, 2 uses -> on-every-use
generic-function: 4 evaluations, 2 uses -> on-every-use
immediately: 0
on-first-use: 0
on-every-use: 4
never: 0
```

All four observations came out as **on every use**. A default implementation is a computed property: the protocol does not store it, and it runs the body again on every read. The three ways of writing a protocol type gave the same result. `any Describable` creates an **existential type**: the real type of the value is stored at runtime and the call is forwarded to it. `some Describable` gives an **opaque type**, which hides the type but keeps it fixed at compile time. The `T: Describable` constraint of a generic function (detailed in lesson 08) reaches the same requirement as well. In all three, `greeting` was computed again on each call; because `twice` reads it twice in one call, the evaluation count in that observation rose to four. In M13/K01 we saw that the common interface `Enumerable` supplies bodies; in Ruby, which body answers from that interface is a separate question. We do not ask it here, we ask only when the body runs. **TS22.** In the measurement no conforming type rewrote the default with its own body; a type giving its own body stayed outside this lesson.

For standard protocols such as `Equatable`, even the compiler can write the default. It is enough for a structure whose stored properties are all equatable to say that it conforms to `Equatable`; the compiler derives the comparison operator.

```swift
// main.swift — Equatable derivation
struct Point: Equatable {
    let x: Int
    let y: Int
}

print(Point(x: 1, y: 2) == Point(x: 1, y: 2))
print(Point(x: 1, y: 2) == Point(x: 2, y: 1))
```

```
true
false
```

We did not write the equality operator; looking at the type definition, the compiler produced a body that compares each field in order. This derivation is a decision made at compile time, not something we measure at run time.

#### The Customization Point

The default implementation in a protocol extension has a subtlety: not every member written in the extension is the same. A member that is also counted among the protocol's requirements becomes a **customization point**. When the conforming type gives its own body, a call made through the protocol type goes to that body too. A member that is not in the requirement list and is written only in the extension is not a customization point: when it is called through the protocol type, the body in the extension runs, even if the conforming type has a member of the same name.

We watch this with two `Probe`s. `standardProbe` counts the default body in the extension, and `customProbe` counts the conforming type's own body. `title` is a requirement of the protocol; `badge` is written only in the extension. `Book` rewrites both with its own body.

```swift
// main.swift — the difference between a requirement and an extension-only member
protocol Badged {
    var standardProbe: Probe { get }
    var customProbe: Probe { get }
    var title: String { get }
}

extension Badged {
    var title: String { standardProbe.eval("default title") }
    var badge: String { standardProbe.eval("default badge") }
}

struct Book: Badged {
    let standardProbe: Probe
    let customProbe: Probe
    var title: String { customProbe.eval("book title") }
    var badge: String { customProbe.eval("book badge") }
}

func probes(_ label: String) -> (standard: Probe, custom: Probe) {
    (Probe("\(label)/extension"), Probe("\(label)/type"))
}

let titleViaProtocol = probes("title-via-protocol")
let badgeViaProtocol = probes("badge-via-protocol")
let badgeViaType = probes("badge-via-type")

let titled: any Badged = Book(standardProbe: titleViaProtocol.standard, customProbe: titleViaProtocol.custom)
_ = titleViaProtocol.custom.use { titled.title }
_ = titleViaProtocol.custom.use { titled.title }

let badged: any Badged = Book(standardProbe: badgeViaProtocol.standard, customProbe: badgeViaProtocol.custom)
_ = badgeViaProtocol.standard.use { badged.badge }
_ = badgeViaProtocol.standard.use { badged.badge }

let book = Book(standardProbe: badgeViaType.standard, customProbe: badgeViaType.custom)
_ = badgeViaType.custom.use { book.badge }
_ = badgeViaType.custom.use { book.badge }

let all = [titleViaProtocol.standard, titleViaProtocol.custom, badgeViaProtocol.standard, badgeViaProtocol.custom, badgeViaType.standard, badgeViaType.custom]
for probe in all { probe.report() }
```

```
title-via-protocol/extension: 0 evaluations, 0 uses -> never
title-via-protocol/type: 2 evaluations, 2 uses -> on-every-use
badge-via-protocol/extension: 2 evaluations, 2 uses -> on-every-use
badge-via-protocol/type: 0 evaluations, 0 uses -> never
badge-via-type/extension: 0 evaluations, 0 uses -> never
badge-via-type/type: 2 evaluations, 2 uses -> on-every-use
```

When `title`, a requirement, was called through the protocol type, `Book`'s own body ran; the default body in the extension stayed `never`. `badge`, which is not a requirement, ran the body in the extension when called through the same `any Badged` value, and `Book`'s own `badge` body stayed `never`. When the same `badge` was called through the concrete `Book` type, the reverse happened: the type's own body ran. This difference shows that writing a member in the requirement list is not only a declaration; it decides which body will run. If you want the types to be able to customize a member added to an extension, you first write it into the protocol's requirements. **TS23.** This difference was measured for structure types and for the `any` protocol type; classes and values returned with `some` were not tried separately.

#### Protocol Composition

If a value has to conform to more than one protocol, we join the types with `&`: `some Named & Priced`. A **protocol composition** does not define a new protocol; it only asks, for the type of a parameter or a return value, for several requirements together. To measure whether a composition changes the moment of the requirements, we use a type that fulfills the two requirements in different ways: `name` is stored, `price` is computed.

```swift
// main.swift — a protocol composition does not change the moment of the requirements
protocol Named { var name: String { get } }
protocol Priced { var price: Int { get } }

struct Product: Named, Priced {
    let name: String
    let items: [Int]
    let tracker: Probe
    var price: Int { tracker.eval(items.reduce(0, +)) }
}

func label(_ value: some Named & Priced) -> String {
    "\(value.name): \(value.price)"
}

let nameProbe = Probe("composition-name")
let priceProbe = Probe("composition-price")

let product = Product(name: nameProbe.eval("Notebook"), items: [3, 4], tracker: priceProbe)
_ = nameProbe.use { label(product) }
_ = nameProbe.use { label(product) }
_ = priceProbe.use { label(product) }

let pair = [nameProbe, priceProbe]
for probe in pair { probe.report() }
```

```
composition-name: 1 evaluations, 2 uses -> immediately
composition-price: 3 evaluations, 1 uses -> on-every-use
```

A composition is only a boundary: the `label` function asks for the requirements of both protocols together, but the moment of each requirement comes from the conforming type's declaration. The stored `name` was evaluated once, when `Product` was built: **immediately**. The computed `price`, on the other hand, ran again each time `label` was called. Of the three calls to `label`, two were counted with `nameProbe` and one with `priceProbe`, so `priceProbe` shows three evaluations in total; this shows which calls the counter passed through and does not indicate a separate moment. Even though `priceProbe` carries a single use, it received three evaluations, so the rule counts it as **on every use** without falling into the ambiguity of a single-use observation. **TS24.** The composition was measured here as a function parameter and with `some`; the `any Named & Priced` spelling was not tried separately.

#### A Constrained Protocol Extension

A `where` condition can be added to a protocol extension: `extension Ranked where Self: Comparable`. The members in such an extension are visible only on types that meet the condition. If the same name is written in both the general extension and the constrained extension, the more specific one, that is the constrained extension, is chosen for a type that meets the condition; a type that does not meet it falls back to the general one. We see which body runs with two `Probe`s: `generalProbe` counts the general extension and `specificProbe` counts the constrained one.

```swift
// main.swift — the constrained extension is chosen when it is more specific
protocol Ranked {
    var points: Int { get }
    var generalProbe: Probe { get }
    var specificProbe: Probe { get }
}

extension Ranked {
    var rank: String { generalProbe.eval("unranked") }
}

extension Ranked where Self: Comparable {
    var rank: String { specificProbe.eval("ranked") }
}

struct Score: Ranked, Comparable {
    let points: Int
    let generalProbe: Probe
    let specificProbe: Probe
    static func < (left: Score, right: Score) -> Bool { left.points < right.points }
    static func == (left: Score, right: Score) -> Bool { left.points == right.points }
}

struct Plain: Ranked {
    let points: Int
    let generalProbe: Probe
    let specificProbe: Probe
}

let comparableGeneral = Probe("comparable/general")
let comparableSpecific = Probe("comparable/constrained")
let plainGeneral = Probe("plain/general")
let plainSpecific = Probe("plain/constrained")

let score = Score(points: 3, generalProbe: comparableGeneral, specificProbe: comparableSpecific)
_ = comparableSpecific.use { score.rank }
_ = comparableSpecific.use { score.rank }

let plain = Plain(points: 3, generalProbe: plainGeneral, specificProbe: plainSpecific)
_ = plainGeneral.use { plain.rank }
_ = plainGeneral.use { plain.rank }

let all = [comparableGeneral, comparableSpecific, plainGeneral, plainSpecific]
for probe in all { probe.report() }
tally(all)
```

```
comparable/general: 0 evaluations, 0 uses -> never
comparable/constrained: 2 evaluations, 2 uses -> on-every-use
plain/general: 2 evaluations, 2 uses -> on-every-use
plain/constrained: 0 evaluations, 0 uses -> never
immediately: 0
on-first-use: 0
on-every-use: 2
never: 2
```

Because `Score` is both `Comparable` and conforms to `Ranked`, the `rank` call went to the body in the constrained extension; the general body stayed `never`. `Plain` is not `Comparable`, so the constrained extension was ignored for it and the general body ran on every call. In both cases the body that ran was evaluated again on every use: the constraint decides which body is chosen, not when it runs. This choice is made at compile time, when the concrete type is known; calling a constrained extension through a protocol value is a separate question and was not measured here. **TS25.** The choice was measured only for calls made through a concrete type.

#### The Bounding Measurement

The protocol does not decide the moment itself: the type that fulfills the requirement does. The `Totaled` protocol below sets a single requirement: `var total: Int { get }`. `StoredTotal` fulfills it with a stored `let`, and `ComputedTotal` with a computed property. Both types are read from the same function; the code that reads cannot see the difference between them.

```swift
// main.swift — the same requirement, two conformances, two moments
protocol Totaled {
    var total: Int { get }
}

struct StoredTotal: Totaled {
    let total: Int
}

struct ComputedTotal: Totaled {
    let items: [Int]
    let tracker: Probe
    var total: Int { tracker.eval(items.reduce(0, +)) }
}

func read<T: Totaled>(_ value: T) -> Int { value.total }

let storedProbe = Probe("stored-conformance")
let computedProbe = Probe("computed-conformance")

let fixedTotal = StoredTotal(total: storedProbe.eval(9))
let derivedTotal = ComputedTotal(items: [4, 5], tracker: computedProbe)

_ = storedProbe.use { read(fixedTotal) }
_ = storedProbe.use { read(fixedTotal) }
_ = computedProbe.use { read(derivedTotal) }
_ = computedProbe.use { read(derivedTotal) }

let pair = [storedProbe, computedProbe]
for probe in pair { probe.report() }
```

```
stored-conformance: 1 evaluations, 2 uses -> immediately
computed-conformance: 2 evaluations, 2 uses -> on-every-use
```

The same `total` requirement, two different moments: the stored conformance is **immediately**, the computed conformance is **on every use**. The protocol does not see this difference; it only says that an `Int` will be returned. So when you read a protocol requirement, you cannot work out the cost of the expression from the protocol's name; you have to look at the declaration of the conforming type. **TS26.** In this measurement the value of `StoredTotal` was built with an expression wrapped in a `Probe`; where a stored value comes from in a real program is a separate question and was not measured here.

#### Summary

- A protocol is a contract that lists requirements; the default implementation written in its extension supplies a body to types that do not fulfill the requirement themselves.
- A computed property in a protocol extension runs again on every read; `any`, `some` and a generic constraint did not change this behavior.
- The compiler derives the implementation from the stored properties for some protocols such as `Equatable`.
- If a stored property fulfills the same requirement, the measurement is **immediately**; if a computed property does, it is **on every use**: the moment is decided by the conforming type, not the protocol.
- This lesson's moment: **on every use** (the default implementation in a protocol extension).

#### Next Step

A protocol extension can add a body to a protocol whose definition belongs to someone else. But does this extension mechanism work only with protocols? The next lesson measures adding methods and properties from the outside to standard types such as `Int` and `String`, and what cannot be added.

### Extensions

Source: https://academia.sh/en/courses/swift/extensions

Measures adding methods, computed properties and protocol conformance to an existing type from the outside; shows that a stored property cannot be added, and the type-level exception.

In the previous lesson the extension of a protocol gave every conforming type a default body, and that body ran again on every read. The concrete form of the same mechanism is extending a type from the outside. You cannot touch the source of a standard type such as `Int` or `String`, but you can write a new method on top of it. This lesson asks when what an extension adds is evaluated.

An **extension** adds new behavior to an existing type without changing its definition. What can be added: methods, computed properties, subscripts, static members, initializers, nested types and protocol conformance. One thing cannot be added, and the weight of this lesson rests on it: a stored instance property.

#### The Measurement Setup

`Probe` sits in the first block, in the same form in every lesson.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

**TS27.** The body of an extension reaches `Probe` as a parameter or as a field of the type being extended; one of these two ways was chosen in the measurements, and binding a global `Probe` to an extension was not tried.

#### Everything Added Is Computed

The block below makes four additions to three types. A method and a `mutating` method are added to `Int`, and a method to `String`. To our own `Meter` type we add a computed property and a protocol conformance: the `CustomStringConvertible` conformance gives the type a text representation, because it asks for the `description` property.

```swift
// main.swift — everything added by an extension runs on every use
struct Meter {
    let value: Int
    let tracker: Probe
}

extension Int {
    func cubed(tracking tracker: Probe) -> Int { tracker.eval(self * self * self) }
    mutating func triple() { self *= 3 }
}

extension String {
    func padded(to width: Int, tracking tracker: Probe) -> String {
        tracker.eval(self + String(repeating: ".", count: max(0, width - count)))
    }
}

extension Meter {
    var centimeters: Int { tracker.eval(value * 100) }
}

extension Meter: CustomStringConvertible {
    var description: String { tracker.eval("\(value) m") }
}

let intMethod = Probe("int-method")
let stringMethod = Probe("string-method")
let computedExtra = Probe("added-computed-property")
let conformance = Probe("added-conformance")

_ = intMethod.use { 3.cubed(tracking: intMethod) }
_ = intMethod.use { 4.cubed(tracking: intMethod) }

_ = stringMethod.use { "ab".padded(to: 5, tracking: stringMethod) }
_ = stringMethod.use { "ab".padded(to: 5, tracking: stringMethod) }

let meter = Meter(value: 7, tracker: computedExtra)
_ = computedExtra.use { meter.centimeters }
_ = computedExtra.use { meter.centimeters }

let described = Meter(value: 7, tracker: conformance)
_ = conformance.use { "\(described)" }
_ = conformance.use { "\(described)" }

var counter = 2
counter.triple()
counter.triple()
print(counter)

let all = [intMethod, stringMethod, computedExtra, conformance]
for probe in all { probe.report() }
tally(all)
```

```
18
int-method: 2 evaluations, 2 uses -> on-every-use
string-method: 2 evaluations, 2 uses -> on-every-use
added-computed-property: 2 evaluations, 2 uses -> on-every-use
added-conformance: 2 evaluations, 2 uses -> on-every-use
immediately: 0
on-first-use: 0
on-every-use: 4
never: 0
```

All four additions came out as **on every use**. A method runs on every call; you expect that. What deserves attention is the `centimeters` property: it is read like a field on the type but it is not stored, it is calculated again on every read. The `CustomStringConvertible` conformance is the same: `description` is built again in every string interpolation. A `mutating` method changes a value in place; `counter` became 18 after two triplings. Because this change is the update of a value and not the evaluation of an expression, it needed no separate `Probe`.

#### A Stored Property Cannot Be Added

If you try to write a stored instance property in an extension, the compiler stops you. We checked this first: the fragment below did not compile on Swift 6.4, so it stays without output.

```swift
extension Meter {
    var unit = "m"
}
```

The reason lies in the memory layout. An instance of a type takes up as much space as the stored properties in its definition add up to; this size is fixed when the type is defined. A field added from the outside would have to change this size outside the definition, so the rule of the language closes stored instance properties to extensions. This is why every property you add with an extension is, by definition, a computed property: the value does not sit anywhere, it is produced when asked for. This is the reason all of the previous block came out as `on-every-use`. **TS28.** The rejection in this section was verified only for instance-level storage; adding a `lazy` or an observed property to an extension was not tried separately.

#### A Constrained Extension

An extension can be added not to every type but only to the types that meet a certain condition. When you write `extension Array where Element: Numeric`, the added members are visible only on arrays whose elements are numeric. A **constrained extension** is the form for types of the `where` condition we saw for protocol extensions in lesson 06. The constraint narrows where the addition applies; it does not change when the added body runs. We measure this by calling the same method on two different array types.

```swift
// main.swift — a constrained extension is added only to arrays that meet the condition
extension Array where Element: Numeric {
    func total(tracking tracker: Probe) -> Element {
        tracker.eval(reduce(0, +))
    }
}

let intTotal = Probe("int-array")
let doubleTotal = Probe("double-array")

let counts = [1, 2, 3]
let weights = [0.5, 1.5]

_ = intTotal.use { counts.total(tracking: intTotal) }
_ = intTotal.use { counts.total(tracking: intTotal) }
_ = doubleTotal.use { weights.total(tracking: doubleTotal) }
_ = doubleTotal.use { weights.total(tracking: doubleTotal) }

let all = [intTotal, doubleTotal]
for probe in all { probe.report() }
```

```
int-array: 2 evaluations, 2 uses -> on-every-use
double-array: 2 evaluations, 2 uses -> on-every-use
```

The same body ran separately on `Int` and `Double` arrays, and in both it ran on every call. The constraint makes sure the `total` method is not visible on a `[String]`; that is a decision made at compile time. The only thing we see at run time is that the method of a constrained extension behaves like an ordinary method: the result is stored nowhere. **TS29.** That the constrained extension is not visible on `[String]` was not verified separately; only the two types that meet the constraint were measured here.

#### An Initializer and a Nested Type in an Extension

An extension can add an initializer to a type as well. For structures this has a special benefit: if you write the initializer in the body of the definition, the memberwise initializer the compiler generates disappears; if you write it in an extension, the two stay together. An extension can also add a **nested type**: an `enum`, `struct` or `class` that is defined inside another type and belongs to it. The block below uses both together. The initializer does a `Probe` evaluation at setup time; the nested type carries a method that runs as it is called.

```swift
// main.swift — an initializer and a nested type in an extension
struct Length {
    let meters: Int
}

extension Length {
    init(centimeters: Int, tracking tracker: Probe) {
        self.init(meters: tracker.eval(centimeters / 100))
    }

    enum Unit {
        case meter, kilometer

        func factor(tracking tracker: Probe) -> Int {
            switch self {
            case .meter: tracker.eval(1)
            case .kilometer: tracker.eval(1000)
            }
        }
    }
}

let initProbe = Probe("initializer-in-extension")
let nestedProbe = Probe("nested-type")

let direct = Length(meters: 5)
let converted = Length(centimeters: 700, tracking: initProbe)
_ = initProbe.use { converted.meters }
_ = initProbe.use { converted.meters }
print(direct.meters)

_ = nestedProbe.use { Length.Unit.kilometer.factor(tracking: nestedProbe) }
_ = nestedProbe.use { Length.Unit.kilometer.factor(tracking: nestedProbe) }

let all = [initProbe, nestedProbe]
for probe in all { probe.report() }
```

```
5
initializer-in-extension: 1 evaluations, 2 uses -> immediately
nested-type: 2 evaluations, 2 uses -> on-every-use
```

The memberwise initializer `Length(meters:)` stayed usable despite the initializer in the extension; the two stood side by side. In the initializer in the extension the evaluation was done once, at setup time, and the result was stored in the `meters` field; reading the field twice produced no new evaluation: **immediately**. This does not contradict added properties running on every read. An initializer does not add a property, it fills an existing stored field; the storage is in the `meters` field of the definition. The method of the nested type, on the other hand, ran on every call like an ordinary method: **on every use**. **TS30.** The nested type was measured here as an `enum`; a nested `struct` or `class` added from an extension was not tried separately.

#### A Subscript in an Extension

An extension can add not only methods and computed properties but also a **subscript**. A subscript is a member that lets you read a value in the form `value[index]`, and its body works like the getter of a computed property. Below we add to `Array` a read that does not crash on an out-of-range index. A subscript can take extra parameters; we pass our measuring setup through this.

```swift
// main.swift — a subscript in an extension runs on every read
extension Array {
    subscript(safe index: Int, tracking tracker: Probe) -> Element? {
        let found: Element? = indices.contains(index) ? self[index] : nil
        return tracker.eval(found)
    }
}

let subscriptProbe = Probe("subscript")
let names = ["a", "b", "c"]

_ = subscriptProbe.use { names[safe: 1, tracking: subscriptProbe] }
_ = subscriptProbe.use { names[safe: 9, tracking: subscriptProbe] }

subscriptProbe.report()
```

```
subscript: 2 evaluations, 2 uses -> on-every-use
```

Two reads gave two evaluations; the out-of-range index also ran the body, and only the result was `nil`. Although a subscript looks like a property, it does no storing: every `[...]` expression runs the body again, **on every use**. This shows that the rule of the section "Everything Added Is Computed" extends to the subscript as well. **TS31.** Only a read-only subscript was measured here; a subscript that writes (`set`) was not tried.

#### A Mutating Method in an Extension

In value types (structures and enumerations), a method that changes `self` is marked `mutating`. A method in an extension obeys the same rule; an extension can add a `mutating` method that is not in the definition. What is changed is the stored field in the definition, so the extension uses the existing storage without adding storage.

```swift
// main.swift — a mutating method in an extension
struct Counter {
    var count = 0
}

extension Counter {
    mutating func bump(tracking tracker: Probe) {
        count += tracker.eval(1)
    }
}

let bumpProbe = Probe("mutating-method")
var counter = Counter()

bumpProbe.use { counter.bump(tracking: bumpProbe) }
bumpProbe.use { counter.bump(tracking: bumpProbe) }

print(counter.count)
bumpProbe.report()
```

```
2
mutating-method: 2 evaluations, 2 uses -> on-every-use
```

The field received two increments in two calls and the value stayed in `counter.count`; the extension added the method itself, not storage. The body ran again on every call: **on every use**. Putting the earlier sections together, the table comes out like this: whatever an extension adds, be it a property, a subscript or a method, the added body runs on every use. The initializer stays outside this table, because it is a setup step and not a read. **TS32.** The `mutating` method was measured only on a structure; it was not verified separately for a class or an enumeration.

#### A Static Member in an Extension

Members that belong to the type and are called with the type itself rather than a value are **static members** (`static`). An extension can add these too. In the Properties lesson we saw a `static let`, and it was set up once, on first access. A static method, on the other hand, is an ordinary method; the distinction is the one between a method and a property. The extension below adds to `Length` a factory called from the type itself, and measures it.

```swift
// main.swift — a static method in an extension
struct Length {
    let meters: Int
}

extension Length {
    static func fromKilometers(_ kilometers: Int, tracking tracker: Probe) -> Length {
        Length(meters: tracker.eval(kilometers * 1000))
    }
}

let staticProbe = Probe("static-method")
_ = staticProbe.use { Length.fromKilometers(2, tracking: staticProbe) }
_ = staticProbe.use { Length.fromKilometers(3, tracking: staticProbe) }

staticProbe.report()
```

```
static-method: 2 evaluations, 2 uses -> on-every-use
```

The static method ran on every call: **on every use**. Belonging to a type does not cache its body; in this measurement caching was seen only in a stored static property such as `static let`. So what you write in an extension depends on whether it is computed or stored, and an extension forbids the stored property anyway. A static stored property does not run into this ban, because the storage is in the type itself and not in the instance. **TS33.** The result of the static method produced a new `Length` each time; instance equality or identity was not measured.

#### The Bounding Measurement

The ban applies only at the instance level. An extension can add a `static let` to a type, because there is a single copy per type and it does not affect the memory layout. We watch when this property is set up with `print`. `Probe` cannot be used here: `Probe` is not `Sendable`, and in the Swift 6 language mode a global or type-level `let` property asks for a `Sendable` type. The `print` line inside the setup is the counter that shows how many times, and in what order, the setup ran.

```swift
// main.swift — a static let in an extension is set up once, on first access
struct Scale {
    let factor: Int
}

extension Scale {
    static let unit: Int = {
        print("unit built")
        return 100
    }()
}

print("before access")
print(Scale.unit)
print(Scale(factor: 3).factor * Scale.unit)
print(Scale.unit)
```

```
before access
unit built
100
300
100
```

The line `unit built` appeared once, right before the first access. The added `static let` gives the moment **on first use** at the type level: it waits until the first read, is set up once, and is stored afterwards. So the storage that is banned at the instance level in an extension is allowed, and lazy, at the type level. Added instance properties were measured as `on-every-use`, and the added type property as `on-first-use`; the two can stand side by side in the same extension. **TS34.** This observation rests on the order of `print`; that the setup runs once when the first access comes from two places at the same time was not measured here.

#### Summary

- An extension adds methods, computed properties, initializers and protocol conformance to an existing type without changing its definition.
- Methods can be added to standard types such as `Int` and `String` as well; a `mutating` method updates the value in place.
- An extension cannot add a stored instance property; every property it adds is computed and runs again on every read.
- A `static let` in an extension is the exception: at the type level, it is set up once, on first access.
- This lesson's moment: **on every use** (a computed property and a method added by an extension).

#### Next Step

The extension added behavior to a type, but the added behavior was tied to a single type. The `cubed` you wrote for `Int` has to be written again for `Double`. The next lesson moves on to generics, which let you write the same body once for many types.

### Generics

Source: https://academia.sh/en/courses/swift/generics

Applies one body to many types with type parameters and constraints; measures the transformer of a lazy sequence on every access and that of an eager map immediately.

In the previous lesson, the `cubed` we wrote for `Int` had to be written again for `Double`. Writing the same body once and applying it to many types is the job of generics. **Generics** let you write a function or a type for a type that is not yet known; the type becomes known at the point of use. In this lesson we measure two behaviors: how a generic body runs on every call, and when the lazy sequences of the standard library call the transformer.

A **type parameter** is a placeholder written inside angle brackets: `<T>`. A **constraint** says which protocol that placeholder has to carry: `<T: Comparable>` accepts only types that can be compared. Without a constraint the body knows nothing about `T`; it cannot even use the `<` operator.

#### The Measurement Setup

`Probe` is the first block in the same form in every lesson. In this lesson, a generic structure and a protocol with an associated type additionally sit in a separate helper file.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

**TS35.** Every observation, apart from `never`, carries two uses; by binding the transformer to single-element arrays, we keep the number of elements from inflating the evaluation count.

```swift
// Stack.swift — a generic stack and a protocol with an associated type
protocol Container {
    associatedtype Item
    var count: Int { get }
    mutating func append(_ item: Item)
}

struct Stack<Element>: Container {
    private(set) var items: [Element] = []
    var count: Int { items.count }
    mutating func append(_ item: Element) { items.append(item) }
    mutating func pop() -> Element? { items.popLast() }
}
```

`Container` carries an **associated type**: `Item`. The protocol does not say which type will be stored, only that such a type will exist; the conforming type decides. `Stack<Element>`, on the other hand, is a **generic structure**: the `Element` placeholder turns into a real type when `Stack<Int>` or `Stack<String>` is written, and the `Item` type of `Container` is inferred as `Element`.

#### A Generic Body Runs on Every Call

The block below puts three things side by side. `largest(_:tracking:)` is a generic function with a `Comparable` constraint, and it is called with two different types. `describe` puts a constraint on the associated type with `where`. The last two observations are two forms of the same transformation: the eager `map` and `lazy.map`.

```swift
// main.swift — a generic function, a generic structure, an eager and a lazy map
func largest<T: Comparable>(_ values: [T], tracking tracker: Probe) -> T? {
    tracker.eval(values.max())
}

func describe<C: Container>(_ box: C) -> Int where C.Item: Comparable {
    box.count
}

let generic = Probe("generic-function")
let eager = Probe("eager-map")
let lazyMap = Probe("lazy-map")

_ = generic.use { largest([3, 9, 4], tracking: generic) }
_ = generic.use { largest(["b", "a"], tracking: generic) }

var stack = Stack<Int>()
stack.append(5)
stack.append(8)
print(describe(stack))
print(stack.pop() ?? -1)

let eagerDoubled = [4].map { eager.eval($0 * 2) }
_ = eager.use { eagerDoubled[0] }
_ = eager.use { eagerDoubled[0] }

let lazyDoubled = [4].lazy.map { lazyMap.eval($0 * 2) }
_ = lazyMap.use { lazyDoubled[0] }
_ = lazyMap.use { lazyDoubled[0] }

let all = [generic, eager, lazyMap]
for probe in all { probe.report() }
tally(all)
```

```
2
8
generic-function: 2 evaluations, 2 uses -> on-every-use
eager-map: 1 evaluations, 2 uses -> immediately
lazy-map: 2 evaluations, 2 uses -> on-every-use
immediately: 1
on-first-use: 0
on-every-use: 2
never: 0
```

The generic function ran on every call: `largest` was evaluated twice in two calls, and the calls were made with different types. A generic body is a single piece of writing but a separate call for each type; the moment of evaluation does not depend on the type parameter. `describe` and `Stack` worked only at the type level: the `where C.Item: Comparable` constraint was satisfied because the `Item` of `Stack<Int>` is `Int`, and the compiler checked this at the call.

The real distinction is in the last two lines. The eager `map` transforms the elements of the array immediately and builds a new array; the transformer ran once while `eagerDoubled` was being built and the two reads did not compute again: **immediately**. `lazy.map`, on the other hand, returns a **lazy wrapper** that stores the transformer; the sequence is built without computing anything, and on every access the transformer is called again. Two accesses to the same element gave two evaluations: **on every use**. **TS36.** This result was measured for an array-based lazy collection; a lazy `Sequence` was not assumed to be traversable again.

A lazy `map` behaves like a computed property, not like a stored property: the result sits nowhere. If you want to do the calculation once and keep it, you derive an array from the wrapper, which is an eager step.

#### A where Constraint Ties Two Types

A constraint put on a single type parameter (`T: Comparable`) forces a protocol. A **`where` clause** can say more: it can ask for the associated types of two type parameters to be the same, or for an associated type to conform to a protocol. The function below takes two containers and compares them only if their element types are the same: `A.Item == B.Item`. This is a compile-time check; in the measurement we see that the moment of evaluation of the body does not change.

```swift
// main.swift — tying the element types of two containers with where
func sameCount<A: Container, B: Container>(_ left: A, _ right: B, tracking tracker: Probe) -> Bool
    where A.Item == B.Item {
    tracker.eval(left.count == right.count)
}

let whereProbe = Probe("where-constraint")

var first = Stack<Int>()
first.append(1)
var second = Stack<Int>()
second.append(2)
second.append(3)

_ = whereProbe.use { sameCount(first, second, tracking: whereProbe) }
_ = whereProbe.use { sameCount(first, first, tracking: whereProbe) }

whereProbe.report()
```

```
where-constraint: 2 evaluations, 2 uses -> on-every-use
```

The body ran twice in two calls: **on every use**. The `where` clause decides whether a call is valid; it takes no part in the cost or the timing of a valid call. That the element types of the two stacks are the same is the compiler's inference here and leaves no trace in the measurement. We did not separately try giving this function two stacks with different element types; we understand what the constraint does from reading the signature, not from the behavior of the body. **TS37.** The rejection by the constraint was not measured in this lesson.

#### A Constrained Extension on a Generic Structure

In lesson 07 we added a constrained extension to `Array`. The same holds for our own generic type: `Stack` can be used with every element type, but a method that asks for comparison makes sense only on stacks where `Element: Comparable`. A constrained extension limits the method to that case. The extension below finds the largest element.

```swift
// main.swift — a constrained extension for Stack
extension Stack where Element: Comparable {
    func largest(tracking tracker: Probe) -> Element? {
        tracker.eval(items.max())
    }
}

let constrained = Probe("constrained-extension")

var numbers = Stack<Int>()
numbers.append(4)
numbers.append(9)

_ = constrained.use { numbers.largest(tracking: constrained) }
_ = constrained.use { numbers.largest(tracking: constrained) }

constrained.report()
```

```
constrained-extension: 2 evaluations, 2 uses -> on-every-use
```

`largest` scans the stack again on every call: **on every use**. There is no cache inside the stack; the extension is subject to the very same rule as in lesson 07 and cannot add a stored field. The advantage of generic types is this: `largest` exists for `Stack<Int>`, while for an element type that cannot be compared, such as `Stack<Counter>`, the method of the constrained extension is not offered. A generic structure is written once, and its set of methods changes with the element type. **TS38.** The measurement was made only on a stack of `Int` elements; that the method is not visible with a non-`Comparable` element was not verified separately.

#### An Opaque Return Type with some

A generic function can choose the return type itself instead of leaving the choice to the caller, and it can hide that. An **opaque return type** is written like `some Sequence<Int>`: the function returns a specific type, but the signature says only "something that conforms to this protocol". The caller does not know the real type; the compiler does. The question here is whether an opaque return changes the moment of evaluation. Two functions make the same transformation; one returns a `lazy` sequence and the other an eager array, both as `some Sequence<Int>`.

```swift
// main.swift — an opaque return with some: lazy and eager
func lazySquares(of values: [Int], tracking tracker: Probe) -> some Sequence<Int> {
    values.lazy.map { tracker.eval($0 * $0) }
}

func eagerSquares(of values: [Int], tracking tracker: Probe) -> some Sequence<Int> {
    values.map { tracker.eval($0 * $0) }
}

let lazyOpaque = Probe("opaque-lazy")
let eagerOpaque = Probe("opaque-eager")

let lazyResult = lazySquares(of: [3], tracking: lazyOpaque)
let eagerResult = eagerSquares(of: [3], tracking: eagerOpaque)

_ = lazyOpaque.use { Array(lazyResult) }
_ = lazyOpaque.use { Array(lazyResult) }
_ = eagerOpaque.use { Array(eagerResult) }
_ = eagerOpaque.use { Array(eagerResult) }

let all = [lazyOpaque, eagerOpaque]
for probe in all { probe.report() }
```

```
opaque-lazy: 2 evaluations, 2 uses -> on-every-use
opaque-eager: 1 evaluations, 2 uses -> immediately
```

Two functions with the same signature gave different moments. The lazy one computed again on every consumption: **on every use**. The eager one computed once during the call, and the two consumptions did not repeat it: **immediately**. `some` hides the real type but does not hide the behavior; whether what comes back is lazy or eager is not written in the signature, but it is visible in the measurement. This is why, in an API that carries an opaque return type, it is useful to state the cost of consumption separately in the documentation. **TS39.** The two functions were measured with a single-element input; the evaluation count with a multi-element input was deliberately left out here.

#### A Generic Function with an @autoclosure Parameter

The `??` operator of the standard library evaluates the right-hand side only if the left-hand side is `nil`. This is done with **`@autoclosure`**: the parameter is wrapped in a closure, but the caller writes an ordinary expression. In our own generic function we set up the same pattern: the `orElse` parameter is called only when needed.

```swift
// main.swift — a generic default value with @autoclosure
func unwrap<T>(_ value: T?, orElse backup: @autoclosure () -> T) -> T {
    if let value { return value }
    return backup()
}

let present = Probe("value-present")
let absent = Probe("value-absent")

let known: Int? = 7
let missing: Int? = nil

_ = present.use { unwrap(known, orElse: present.eval(0)) }
_ = present.use { unwrap(known, orElse: present.eval(0)) }
_ = absent.use { unwrap(missing, orElse: absent.eval(0)) }
_ = absent.use { unwrap(missing, orElse: absent.eval(0)) }

let all = [present, absent]
for probe in all { probe.report() }
tally(all)
```

```
value-present: 0 evaluations, 2 uses -> never
value-absent: 2 evaluations, 2 uses -> on-every-use
immediately: 0
on-first-use: 0
on-every-use: 1
never: 1
```

When there was a value, the backup expression was never evaluated: **never**. When there was no value, it was evaluated on every call: **on every use**. The generic function knows nothing about `T`, but its own body decides whether the closure will be called; what is deferred is independent of the type. This agrees with the main theme of the lesson: a generic body runs on every call, and even an expression inside the body may not run. **TS40.** The measurement was made with `Int`; it was not assumed that the result stays the same for types where the deferred expression has a side effect.

#### A Generic Structure Stores Its Elements

A value you put inside a generic structure is evaluated at the moment of insertion, whatever the type parameter is, and the structure holds that value. The expression given to `Stack<Int>` with `append` is computed on the caller's side before `append` is called; the stack stores only the result. We measure this because it is important to see that a generic container does not behave as "lazy" or "computed", it only carries.

```swift
// main.swift — a generic structure stores the value added to it
let element = Probe("stack-element")

var holder = Stack<Int>()
holder.append(element.eval(5))

_ = element.use { holder.count }
_ = element.use { holder.count }
_ = element.use { holder.pop() }

element.report()
```

```
stack-element: 1 evaluations, 3 uses -> immediately
```

The expression was evaluated once, on the line of insertion; reading the stack or pulling the element did not compute it again: **immediately**. In this respect a generic structure behaves like a stored property. If you want computed behavior, you give the structure a closure instead of a value, and in this case what is stored is the closure. **TS41.** It was measured with a single insertion and with `Int`; cases where the stack fills up and is resized are outside this measurement.

#### The Bounding Measurement

A lazy sequence has one transformer call per element, and the call is made only for the element that is read. The array below has two elements. The transformer uses one `Probe` for the first element and the other for the second. The sequence is read only with `first`.

```swift
// main.swift — the same lazy sequence, both on every use and never
let hot = Probe("read-element")
let cold = Probe("unread-element")

let pipeline = [10, 20].lazy.map { value -> Int in
    value == 10 ? hot.eval(value + 1) : cold.eval(value + 1)
}

_ = hot.use { pipeline.first }
_ = hot.use { pipeline.first }
_ = cold.use { pipeline.first }
_ = cold.use { pipeline.first }

hot.report()
cold.report()
```

```
read-element: 4 evaluations, 2 uses -> on-every-use
unread-element: 0 evaluations, 2 uses -> never
```

A single lazy sequence carried two separate moments. The first element was transformed again on every `first` call. There are four `first` calls in the block and all four read the first element; `hot` counted only its own two uses, but it saw all four evaluations: **on every use**. Nobody reached for the second element, and the transformer never ran on it: **never**, even with two uses. A lazy sequence does the opposite of the eager `map`: the eager array computes all elements immediately, the lazy sequence computes none of them beforehand. **TS42.** `first` evaluated only the first element; this is a result that depends on the `first` implementation of the collection and was measured on Swift 6.4.

#### Summary

- Generics let you write a body once with a type parameter and use it with many types; a constraint says which protocol the type has to carry.
- An associated type states that a protocol needs a type but that the conforming type will decide it; a constraint is put on this type with `where`.
- The eager `map` calls the transformer immediately; `lazy.map` calls it again on every access.
- For a never-read element of a lazy sequence, the transformer does not run; the same sequence can carry both **on every use** and **never**.
- This lesson's moment: **on every use** (the `lazy.map` transformer, two accesses to the same element).

#### Next Step

So far every body ran to its end. But if something goes wrong in the middle of a body, what happens to the remaining lines? The next lesson measures throwing an error, and that the statements after a throw are not evaluated.

### Error Handling

Source: https://academia.sh/en/courses/swift/error-handling

Measures that nothing after the `throw` line in the body of a throwing function ever runs, while a `defer` block runs on every exit.

So far every body has run to its end, but reaching the end is not guaranteed. An **error** is the way a function tells its caller that it cannot produce a result. In Swift this is done by throwing a value: the `throw` statement cuts the body at that point and hands control to the code that handles the error. In this lesson we measure what happens to the rest of the cut body.

An error value can be of any type that conforms to the `Error` protocol; in practice it is an `enum`, because error kinds form a finite, nameable set. A **throwing function** carries `throws` in its signature, and the caller has to call it with `try`. The `throws(ParseError)` form writes the single error type that can be thrown into the signature.

#### The Measurement Setup

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

**TS43.** To measure the error case, a `Probe` is passed to the function that is called with broken input; the statement after the `throw` uses that `Probe`. The error is printed as a `case`; its description text is not printed.

#### Nothing After a Throw Runs

```swift
// Parsing.swift — the error type and the throwing function
enum ParseError: Error {
    case empty, notNumber, negative
}

func parse(_ text: String) throws(ParseError) -> Int {
    if text.isEmpty { throw .empty }
    guard let value = Int(text) else { throw .notNumber }
    if value < 0 { throw .negative }
    return value
}

func load(_ text: String, afterThrow tracker: Probe) throws(ParseError) -> Int {
    let value = try parse(text)
    return tracker.eval(value)
}
```

The error type, `parse` and `load` sit in a separate file because several measurements use them. The measurement file builds on top of it.

```swift
// main.swift — typed throws, do/catch, try? and rethrows
func apply(_ work: () throws -> Int) rethrows -> Int {
    try work()
}

do {
    _ = try parse("")
} catch {
    print(error)
}

do {
    _ = try parse("7x")
} catch .notNumber {
    print("not a number")
} catch {
    print(error)
}

print((try? parse("-3")) ?? -1)
print((try? apply { try parse("41") }) ?? -1)

let broken = Probe("broken-input")
let healthy = Probe("healthy-input")

_ = broken.use { try? load("abc", afterThrow: broken) }
_ = broken.use { try? load("", afterThrow: broken) }
_ = healthy.use { try? load("12", afterThrow: healthy) }
_ = healthy.use { try? load("13", afterThrow: healthy) }

let all = [broken, healthy]
for probe in all { probe.report() }
tally(all)
```

```
empty
not a number
-1
41
broken-input: 0 evaluations, 2 uses -> never
healthy-input: 2 evaluations, 2 uses -> on-every-use
immediately: 0
on-first-use: 0
on-every-use: 1
never: 1
```

When the `try parse(text)` line throws, `load` ends right there. The `tracker.eval(value)` expression after it never ran in either of the two calls with broken input: **never**. With healthy input every call went to the end and was evaluated again on each call: **on every use**. The error path cuts the body like a short circuit; for the statements that follow there is no "maybe it runs".

`do`/`catch` handles the error: `catch .notNumber` writes a pattern, and the last `catch` takes every remaining error and provides the implicit `error` value. `try?` turns the error into `nil`, so a default value can be supplied with `??`. `rethrows` marks a function that throws if the closure it takes as a parameter throws, and does not throw otherwise; `apply` above behaves according to whether its closure throws. **TS44.** The printed error form is the `case` name; this was measured because the error `enum` carries no associated values, and `case`s with associated values were not tried.

The difference between `throws(ParseError)` and plain `throws` is that the set of errors the caller may meet shows up in the signature. When a function with a written type is called inside a `do throws(ParseError)` block, the `error` value of the `catch` block is directly a `ParseError`, and a pattern such as `catch .notNumber` is matched against the `case` names of the `enum` at compile time. Untyped `throws` tells the caller only that "some `Error` may be thrown". The evaluation rule is the same in both forms: the moment `throw` runs, the body ends, and this is a behavior you can see from the counter of the measurement setup.

The practical consequence of this rule is that the position of a statement with a side effect on the error path matters. A statement that increments a counter, writes a record or changes a resource runs on every path if it stands before the `try` line, and only on the successful path if it stands after. Which one you want is the contract of the function: writing first and validating afterwards gives a different behavior from validating first and writing afterwards.

`try?` does not change this rule, only the appearance of the error: a call that throws returns `nil`, but what follows the throwing point still does not run. This is why the `broken-input` line of the measurement is **never** even though it was called with `try?`. Swallowing the error and the body continuing are two separate things.

#### The Question-Mark and the Forced try

There are three short ways to handle an error: `do`/`catch`, `try?` and the forced `try`. **`try?`** turns a throwing call into an optional value; the error becomes `nil` and a success becomes the wrapped value. The **forced `try`** (the exclamation-mark form) is a claim that "this call never throws"; if it throws, the program crashes. Neither changes the call itself, they only choose where the error goes. So they are expected to look alike in terms of the moment of evaluation. The block below measures both with input that does not throw; calling the forced `try` with throwing input would crash the program, so this lesson does not measure that.

```swift
// main.swift — try? and the forced try, with non-throwing input
let optionalProbe = Probe("try-question")
let forcedProbe = Probe("try-bang")

let first = optionalProbe.use { try? load("21", afterThrow: optionalProbe) }
let second = optionalProbe.use { try? load("22", afterThrow: optionalProbe) }
let third = forcedProbe.use { try! load("23", afterThrow: forcedProbe) }
let fourth = forcedProbe.use { try! load("24", afterThrow: forcedProbe) }

print(first ?? -1, second ?? -1, third, fourth)

let all = [optionalProbe, forcedProbe]
for probe in all { probe.report() }
```

```
21 22 23 24
try-question: 2 evaluations, 2 uses -> on-every-use
try-bang: 2 evaluations, 2 uses -> on-every-use
```

Both forms ran the body on every call: **on every use**. Neither `try?` nor the forced `try` brings a cache or a deferral; both execute the call right there, immediately. The difference is in the shape of the result: `try?` gives an `Int?` that may be empty, the forced form gives a plain `Int` that cannot be empty. The behavior of the error path is the side that is not measured here. With `try?` a `nil` comes back and the program goes on, with the forced form the program stops. **TS45.** The measurement covers only the path that does not throw; the error path of the forced `try` was deliberately not measured.

#### When rethrows Calls the Closure

A function marked `rethrows` may throw if the closure it takes throws, and never throws if the closure does not. For the caller, the visible result is that there is no need to write `try` when the closure does not throw. But when does the body of the closure run? `apply` calls the closure immediately; in the measurement we put two cases side by side: a closure that does not throw, and a closure that throws, but calls `parse` before it gets to the point of running its own statement.

```swift
// main.swift — rethrows with a throwing and a non-throwing closure
func apply(_ work: () throws -> Int) rethrows -> Int {
    try work()
}

let plain = Probe("non-throwing-closure")
let throwing = Probe("throwing-closure")

_ = plain.use { apply { plain.eval(5) } }
_ = plain.use { apply { plain.eval(6) } }

_ = throwing.use {
    try? apply {
        let value = try parse("x")
        return throwing.eval(value)
    }
}
_ = throwing.use {
    try? apply {
        let value = try parse("")
        return throwing.eval(value)
    }
}

let all = [plain, throwing]
for probe in all { probe.report() }
```

```
non-throwing-closure: 2 evaluations, 2 uses -> on-every-use
throwing-closure: 0 evaluations, 2 uses -> never
```

The non-throwing closure was called without `try` and ran on every call. In the two calls where the throwing closure was cut at the `parse` line, the `eval` after it was never evaluated. So `rethrows` adds no rule to the body of the closure: the closure runs the moment it is called, and what happens inside it is subject to the `throw` rule of the first section. `rethrows` decides only how the error passes outward, that is, whether the signature requires `try`. **TS46.** The default case, where the closure is passed as a parameter, was measured; a closure stored in a property and called later was not tried.

#### Catching a Typed Error Exhaustively

In the introduction we said that the `throws(ParseError)` form carries the set of errors into the signature. The concrete counterpart shows on the catching side: when a `do` block declares the thrown type with `do throws(ParseError)`, the `error` inside `catch` is obtained as a `ParseError`, and a `switch` can cover all the `case`s without a `default`. When a new `case` is added, the compiler points to that `switch`. The function below does this with the `do throws(ParseError)` form and returns a separate recovery value for each `case`.

```swift
// main.swift — an exhaustive switch with a typed error
func recover(_ text: String, handler: Probe) -> Int {
    do throws(ParseError) {
        return try parse(text)
    } catch {
        switch error {
        case .empty: return handler.eval(0)
        case .notNumber: return handler.eval(-1)
        case .negative: return handler.eval(-2)
        }
    }
}

let handler = Probe("catch-body")
let inputs = ["5", "", "q", "-9"]
var values: [Int] = []
for text in inputs {
    values.append(handler.use { recover(text, handler: handler) })
}

print(values)
handler.report()
```

```
[5, 0, -1, -2]
catch-body: 3 evaluations, 4 uses -> on-every-use
```

Three of the four calls had errors, and the `catch` body ran only in those three: four uses and three evaluations. The successful call never reached the `catch`. Because the body was evaluated more than once, the rule counts it as **on every use**; but those evaluations cover not every call, only the calls with errors. The `switch` in the same block has no `default`; this is a consequence of the caught type being known as `ParseError`. With untyped `throws` the same `switch` would not compile, because `error` would be an `any Error` and a `default` would be required. **TS47.** This behavior was measured on Swift 6.4 with the `do throws(ParseError)` form; it was not assumed that the form exists in older versions.

#### Turning an Error into a Value: Result

Instead of catching an error right away, you can also carry it as a value. **`Result`** is an enum that stores either a success or an error. The `Result { ... }` form calls the closure immediately and puts the outcome or the error inside. After that you can read the value with `get()` as often as you want. The question here is: does the body run again when a `Result` is read?

```swift
// main.swift — Result turns an error into a value, the body runs once
let resultProbe = Probe("result")

let result = Result<Int, ParseError>(catching: { () throws(ParseError) -> Int in
    try load("8", afterThrow: resultProbe)
})

_ = resultProbe.use { try? result.get() }
_ = resultProbe.use { try? result.get() }

resultProbe.report()
```

```
result: 1 evaluations, 2 uses -> immediately
```

The body ran once, while the `Result` was being built, and the two `get()` calls did not run it again: **immediately**. This is the opposite of executing the call again each time with `try?`. `Result` also makes the error a value, so the throwing point and the handling point can be separated: an error is caught in one place, handled in another, and the body does not run again while it is handled. **TS48.** The `Result` initializer was measured with input that does not throw; it was not claimed by this measurement that the body also runs once with faulty input.

#### An Error on an Array: Stopping at the First Error

The standard library's `map` is a `rethrows` function that throws itself if its closure throws. When we transform an array of three elements and the second element gives an error, what happens to the third? We bind a separate `Probe` to each element and call the transformation with `try?`; in the end we can see which elements were evaluated.

```swift
// main.swift — map stops at the first error
let inputs = ["4", "x", "6"]
let probes = [Probe("first"), Probe("second"), Probe("third")]

let converted = try? inputs.indices.map { index -> Int in
    try load(inputs[index], afterThrow: probes[index])
}

print(converted == nil)
for probe in probes { probe.report() }
```

```
true
first: 1 evaluations, 0 uses -> immediately
second: 0 evaluations, 0 uses -> never
third: 0 evaluations, 0 uses -> never
```

The first element was transformed, the second element gave an error and the third was never reached. `use` was not called in this measurement; the question is how many elements were evaluated, which is why the use count is zero and the first one's **immediately** label shows only the single evaluation. A `map` that moves along the array is cut at the first error; for the following elements there is no behavior of "try anyway". This is the `throw` rule of a single function body reflected at the array level: what is cut is not the rest of a body but the remaining turns of the loop. If you want to try all the elements and collect the errors, you have to turn each element into its own `Result`. **TS49.** The measurement was made with `indices.map`; it was not assumed that other collection types or `lazy` sequences stop in the same way.

#### The Bounding Measurement

The rule that nothing after a throw runs has one exception: a **`defer`** block runs even when the scope is left with `return` or `throw`. If the program ends with `fatalError` or `exit`, `defer` does not run. Both the broken-input path and the successful path run the `defer`.

```swift
// main.swift — defer runs on every exit
func guarded(_ text: String, cleanup: Probe) throws(ParseError) -> Int {
    defer { _ = cleanup.eval(0) }
    return try parse(text)
}

let cleanup = Probe("defer-cleanup")
_ = cleanup.use { try? guarded("12", cleanup: cleanup) }
_ = cleanup.use { try? guarded("x", cleanup: cleanup) }
cleanup.report()
```

```
defer-cleanup: 2 evaluations, 2 uses -> on-every-use
```

In both of the two calls, one successful and one with an error, the `defer` ran: **on every use**. This has to be read together with the previous measurement. On the same error path, the ordinary statement after the `throw` stayed **never**; the `defer` ran. Work that has to be done on every exit path, such as releasing resources or rolling back a state, you write in a `defer`, not in an ordinary statement. **TS50.** The `defer` measurement was made in a function with a single exit point; its ordering across several `return` paths was not measured.

#### Summary

- An error type is an `enum` that conforms to `Error`; `throws(ParseError)` writes the type that can be thrown into the signature.
- `do`/`catch` handles with a pattern, `try?` turns the error into `nil`, and `rethrows` passes on the error of a closure.
- `throw` cuts the body at that point; the statements after it are never evaluated.
- A `defer` block runs the same way on a successful and on an erroneous exit.
- This lesson's moment: **never** (the statement after the `throw` with broken input).

#### Next Step

Where a property or a function can be seen from is also a design decision. The next lesson measures access control and how a `private` cache looks from the outside.

### Access Control

Source: https://academia.sh/en/courses/swift/access-control

Measures that making a cache `private` does not change the moment of evaluation, and that access control is decided at compile time.

Error handling was the way a function tells its caller that it cannot produce a result. Access control answers a different question: who can see a member? An **access level** says which pieces of code can see a declaration. Swift has six levels, from narrow to wide visibility: `private` is the declaration's own scope and its extensions in the same file, `fileprivate` is the same file, `internal` is the same module, `package` is the modules in the same package, `public` is other modules, and `open` lets other modules subclass and override as well. The default is `internal`. Because this course runs in a single module, we cannot measure the difference between `package`, `public` and `open`; knowing their names is enough.

**`private(set)`** keeps reading wide and writing narrow for a property: it can be read from outside and written only from the declaration itself. The counters of `Probe` are written this way.

#### The Measurement Setup

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

**TS51.** The measurement has two helper files: `Ledger.swift`, which holds the cached and uncached totals, and `Vault.swift`, which stores a `private` member. The rejection of access to a `private` member from another file is shown not in the measured block but in a separate source fragment.

```swift
// Ledger.swift — a private lazy cache, a private computed property and an open lazy
final class Ledger {
    private let source: Probe
    private lazy var cachedTotal: Int = source.eval(10)
    private var computedTotal: Int { source.eval(10) }
    private(set) var entries = 0

    init(source: Probe) { self.source = source }
    func record() { entries += 1 }
    var total: Int { cachedTotal }
    var freshTotal: Int { computedTotal }
}

final class OpenLedger {
    let source: Probe
    lazy var cachedTotal: Int = source.eval(10)
    init(source: Probe) { self.source = source }
}
```

```swift
// Vault.swift — a private member
struct Vault {
    private var secret = 42
    var hint: Int { secret % 10 }
}
```

#### The Cache Is Private, the Evaluation Is the Same

`Ledger` caches the total in `private lazy var cachedTotal` and exposes it through a computed property named `total`. Someone looking from outside sees only `total`; the existence of the cache is an implementation detail.

```swift
// main.swift — measuring a private lazy cache through outside access
let cached = Probe("private-lazy")
let ledger = Ledger(source: cached)
ledger.record()
ledger.record()
print(ledger.entries)
print(Vault().hint)

_ = cached.use { ledger.total }
_ = cached.use { ledger.total }
cached.report()
```

```
2
2
private-lazy: 1 evaluations, 2 uses -> on-first-use
```

`total` was read twice and the source expression was evaluated once: **on first use**. Being `private` did not turn the cache into anything other than a stored value; the first access did the calculation and kept the result, and the second access handed back what was kept. `Vault().hint`, on the other hand, gave out a value derived from a `private` member without showing the member. `ledger.entries` could be read; writing it needed `record()`.

We can see that the writing side is closed by trying to assign a value from outside to a property marked `private(set)`. Outside the file of the declaration, this line does not compile:

```swift
let ledger = Ledger(source: Probe("ledger"))
ledger.entries = 5
```

The same rule applies to reading a `private` member. The `secret` field of `Vault` cannot be seen from a line written in another file:

```swift
let vault = Vault()
print(vault.secret)
```

**TS52.** The compiler gave an error for both rejections; both were verified with separate temporary blocks, and the error texts are not printed here because the text depends on the version.

The difference between `private` and `fileprivate` is where the boundary of visibility is drawn. A `private` member is visible inside the scope of the declaration and its extensions in the same file; a `fileprivate` member is open to every declaration in the same file. If two types sit side by side in the same file, a `fileprivate` member can be reached from both, while a `private` one cannot. This is why `Vault` and `Ledger` were kept in separate files: so that it stays clear which boundary the rejection comes from.

Choosing an access level is a design decision, but it has no measurable effect. Making the cache `private` lets you replace the cache with another form later: the code that uses `Ledger` depends only on `total`, not on `cachedTotal`, so even if the storage form inside changes, the code outside keeps compiling. This is a contract boundary; when it will be evaluated is another axis, as we measure below.

Opening a member wider than necessary, on the other hand, is a decision that is hard to take back. Once a cache that is `internal` has been bound to from outside, pulling it back to `private` breaks those bindings. Starting narrow and widening when needed is often cheaper than the reverse, because widening does not break existing calls and narrowing does. In a library, widening has a cost too: every member you open is a new contract.

#### fileprivate: The File Boundary

In the previous section we explained the difference between `private` and `fileprivate`; now we use it in a measured block. If two types sit side by side in the same file, a `fileprivate` member is visible from both. Below, the `Auditor` type in the same file reads the `fileprivate` computed property of a type named `Account`. If the same property were `private`, this access from another type would not compile even in the same file; this lesson does not measure that rejection separately.

```swift
// main.swift — a fileprivate member is read from another type in the same file
struct Account {
    fileprivate let source: Probe
    fileprivate var balance: Int { source.eval(100) }
}

struct Auditor {
    func read(_ account: Account) -> Int {
        account.balance
    }
}

let audit = Probe("fileprivate")
let account = Account(source: audit)
let auditor = Auditor()

_ = audit.use { auditor.read(account) }
_ = audit.use { auditor.read(account) }

audit.report()
```

```
fileprivate: 2 evaluations, 2 uses -> on-every-use
```

`Auditor` could read the `fileprivate` property of `Account`, and the property ran again on every read: **on every use**. The access level widened (from `private` to `fileprivate`) and the moment of evaluation stayed the same. This repeats the claim of the bounding measurement from a different direction: opening up access does not change the moment either. `fileprivate` lets you think of a file as a small unit; you put two tightly coupled types in the same file and open their internal details only to each other. **TS53.** The measurement was made in a single file; compiling the lesson blocks as separate files would be the way to try this boundary, but the `private` rejection above already shows the same boundary.

#### Giving an Access Level to an Extension

An access modifier can be written not on a single member but on a whole extension: `fileprivate extension Tax { ... }`. The members inside the extension take the level of the extension if they carry no modifier of their own. This is the short way to narrow a group of helpers all at once. The extension below closes two members to the file at the same time.

```swift
// main.swift — the access level given to an extension passes to its members
struct Tax {
    let source: Probe
}

fileprivate extension Tax {
    var rate: Int { source.eval(18) }
    func applied(to amount: Int) -> Int { amount * rate / 100 }
}

let taxProbe = Probe("fileprivate-extension")
let tax = Tax(source: taxProbe)

_ = taxProbe.use { tax.applied(to: 200) }
_ = taxProbe.use { tax.rate }

taxProbe.report()
```

```
fileprivate-extension: 2 evaluations, 2 uses -> on-every-use
```

Both the method and the property were closed with a single `fileprivate`, and both could be called from the same file. The first call read `rate` from inside the method, the second read it directly; on both paths the body ran each time: **on every use**. A modifier at the extension level does not touch when the members are evaluated; it only decides who can see them. Giving an access level to an extension to hide the helpers of a type in one place removes the need to write the modifier on each member separately. **TS54.** In the measurement the members in the extension had no modifier of their own; whether a member can write a level wider than the extension was not tried.

#### private(set): Reading Is a Stored Value

A property marked `private(set)` is read from outside and written from inside. The property in this measurement is a stored property; reading it triggers no calculation. `private(set)` can also be written on a computed property, but that is not what is measured here. Writing comes only from the type's own methods. In the measurement we separate the moment of writing (the initializer) from the moment of reading.

```swift
// main.swift — reading a stored value with private(set)
struct Gauge {
    private(set) var level: Int

    init(tracking tracker: Probe) {
        level = tracker.eval(3)
    }
}

let gaugeProbe = Probe("private-set")
let gauge = Gauge(tracking: gaugeProbe)

_ = gaugeProbe.use { gauge.level }
_ = gaugeProbe.use { gauge.level }

gaugeProbe.report()
```

```
private-set: 1 evaluations, 2 uses -> immediately
```

The value was written once, in the initializer, and the two reads did not produce a new evaluation: **immediately**. Having the reading side wide is free; having the writing side narrow is enforced at compile time, and the rejection was shown earlier in this lesson. `private(set)` therefore gives two things together: a property that looks constant from outside and storage that can be changed inside. **TS55.** In the measurement the value was written only in the initializer; state changed later by a method was not measured.

#### public and open: The Module Boundary Cannot Be Measured

All the measurements in this lesson run in a single module. `public` and `open` change visibility from another module: a `public` type can be used from outside but cannot be subclassed, an `open` class can be subclassed from outside and its members can be overridden. Within a single module the difference between the two is invisible, and a single module cannot show the difference between `package`, `public` and `open` either; so we do not invent a measurement of the moment of evaluation for them. Still, we can measure that a `public` member compiles in a single module and that the moment of evaluation does not change.

```swift
// main.swift — a public member behaves the same in the same module
public struct Rate {
    private let reader: () -> Int
    public var current: Int { reader() }
    public init(reader: @escaping () -> Int) { self.reader = reader }
}

let publicProbe = Probe("public")
let rate = Rate(reader: { publicProbe.eval(7) })

_ = publicProbe.use { rate.current }
_ = publicProbe.use { rate.current }

publicProbe.report()
```

```
public: 2 evaluations, 2 uses -> on-every-use
```

The `public` computed property (bound through a closure because the measurement class is `internal`) ran on every read in the same way as an `internal` one: **on every use**. This result says that writing `public` did not change the evaluation; the real difference between `public` and `internal` appears between a library and the application that uses it. If you write a library, everything you mark `public` becomes a contract, and breaking that contract breaks all the code that uses it. There is also a rule: the type used in the signature of a `public` member cannot be at a narrower level than the member. Because `Probe` is `internal` in this lesson, a `public` property cannot bind to it directly; this is why we used a closure in the measurement. `open` goes one step further: allowing subclassing also brings the internal workings of the type into the contract. **TS56.** `open` was not measured in this lesson and its difference cannot be shown in a single module; only the fact that the `public` form compiles and does not change the behavior was measured.

#### A private Nested Type

A type defined inside a type carries an access level too. A `private` nested type is visible only from inside the enclosing type. The code outside is not aware that the type exists, but it makes use of the behavior it offers. This is the strongest form of hiding an implementation detail completely. `Printer` below hands the formatting to a `private` nested structure.

```swift
// main.swift — a private nested type is invisible to the outside but works
struct Printer {
    private struct Formatter {
        let source: Probe
        func format(_ number: Int) -> String {
            "\(source.eval(number))"
        }
    }

    private let formatter: Formatter

    init(source: Probe) {
        formatter = Formatter(source: source)
    }

    func render(_ number: Int) -> String {
        formatter.format(number)
    }
}

let nestedProbe = Probe("private-nested")
let printer = Printer(source: nestedProbe)

print(nestedProbe.use { printer.render(5) })
_ = nestedProbe.use { printer.render(6) }

nestedProbe.report()
```

```
5
private-nested: 2 evaluations, 2 uses -> on-every-use
```

The code outside called only `render`; the name of the `Formatter` type never appeared in `main.swift`. The method of the nested type ran on every call: **on every use**. Hiding did not change the behavior; it removed the type from the outside. This completes the shared result of the previous sections: an access level is a visibility decision, not a timing decision. In short, the narrower the surface you open to the outside, the more you can change inside; in this measurement hiding did not change the moment of evaluation either. In a design, replacing `Formatter` later with another type does not affect the users of `Printer`, because the only thing they depend on is `render`. **TS57.** In the measurement the nested type was a structure; it was not separately verified for a nested class or `enum`.

#### The Bounding Measurement

The previous result can be read as "a private cache is on-first-use"; this reading is misleading. An access level does not determine the moment of evaluation. The same `lazy` declaration also gives `on-first-use` when it is `internal`, while a `private` computed property gives `on-every-use` in spite of being `private`. What determines the moment is the kind of the property: stored, `lazy` or computed.

```swift
// main.swift — an access level does not change the moment
let openProbe = Probe("internal-lazy")
let openLedger = OpenLedger(source: openProbe)
_ = openProbe.use { openLedger.cachedTotal }
_ = openProbe.use { openLedger.cachedTotal }

let freshProbe = Probe("private-computed")
let freshLedger = Ledger(source: freshProbe)
_ = freshProbe.use { freshLedger.freshTotal }
_ = freshProbe.use { freshLedger.freshTotal }

openProbe.report()
freshProbe.report()
```

```
internal-lazy: 1 evaluations, 2 uses -> on-first-use
private-computed: 2 evaluations, 2 uses -> on-every-use
```

The `internal lazy` again gave **on first use**, and the `private` computed property again gave **on every use**. Access control is a **compile-time** decision: the compiler accepts or rejects a line, and does not interfere with the order of evaluation of the running program. So an access level is not one of the moments we measure, but a rule that stays outside them.

This distinction is also a signal for someone reading the code: seeing that a member is `private` tells you that the effect of changing it will stay inside the declaration. For an `internal` member, you have to assume that the effect can reach anywhere in the module.

#### Summary

- There are six access levels: `private`, `fileprivate`, `internal`, `package`, `public`, `open`; the default is `internal`.
- `private(set)` keeps reading wide and writing narrow; assignment from outside does not compile.
- Access to a `private` member from another file does not compile.
- An access level does not change the moment of evaluation; the kind of the property determines the moment.
- This lesson's moment: **on first use** (two outside accesses to a `private lazy` cache).

#### Next Step

The type system topic ends here. The next topic moves on to memory management: when an object is released and when `deinit` runs.

## Memory and Advanced Features

Automatic reference counting, breaking retain cycles with strong, weak and unowned references, capturing in closures, property wrappers, result builders, and isolation under strict concurrency checking.

### Automatic Reference Counting

Source: https://academia.sh/en/courses/swift/automatic-reference-counting

Measures the point at which deinit runs once the last strong reference is released along four release paths, and shows that a second reference postpones that moment.

The previous lesson measured that an access level changes who can see a name but not the moment: a hidden `lazy` cache was built on first use even when it was `private`. This lesson moves from visibility to the question of when an object is destroyed. Class instances are managed by **automatic reference counting (ARC)**: the number of strong references to each instance is tracked, and the instance is destroyed at the moment that number drops to zero. While it is being destroyed, the class's `deinit` body runs. The question is the question of this course: when is the `deinit` body evaluated?

Earlier courses asked where a lifetime ends and who owns the memory. This lesson makes neither of those the category. The lifetime boundary and the owner are not measured; what is measured is after which line, and how many times, the `deinit` body runs, that is, the moment. The core comes first. `Probe` records how many times an expression was evaluated and whether that happened before or after use; `tally` counts the four moments.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```


The class under measurement is `Session`. Its `deinit` body first prints a line and then notifies the owning `Probe` through `eval`. That way both the `print` order and the `Probe` counter show the same event.

```swift
// Session.swift — class that writes to a Probe in its deinit
final class Session {
    let name: String
    let owner: Probe

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit \(name)")
        _ = owner.eval(name)
    }
}
```


#### Four Release Paths

The first measurement releases a `Session` instance in four different ways. The first path is the end of a `do` scope. The second is assigning `nil` to an optional variable. The third is removing the instance from an array with `removeLast()`. The fourth is building a new instance in each iteration of a `for` loop. Each path runs at least twice, because the `Probe` rule asks for at least two uses for every observation other than `never`. The rule counts, it does not read intent.

```swift
// main.swift — which release runs deinit
let scopeEnd = Probe("scope-end")
let niled = Probe("nil-assignment")
let removed = Probe("array-removal")
let looped = Probe("loop-iteration")

for round in 1...2 {
    _ = scopeEnd.use {
        do {
            let temp = Session("scope-\(round)", owner: scopeEnd)
            print("used \(temp.name)")
        }
    }
}

for round in 1...2 {
    var held: Session? = Session("nil-\(round)", owner: niled)
    _ = niled.use { held = nil }
    print("after \(held == nil)")
}

var list = [Session("array-1", owner: removed), Session("array-2", owner: removed)]
_ = removed.use { list.removeLast() }
_ = removed.use { list.removeLast() }
print("remaining in array \(list.count)")

for round in 1...3 {
    let item = Session("loop-\(round)", owner: looped)
    _ = looped.use { item.name }
}

let probes = [scopeEnd, niled, removed, looped]
for probe in probes {
    probe.report()
}
tally(probes)
```

```
used scope-1
deinit scope-1
used scope-2
deinit scope-2
deinit nil-1
after true
deinit nil-2
after true
deinit array-2
deinit array-1
remaining in array 0
deinit loop-1
deinit loop-2
deinit loop-3
scope-end: 2 evaluations, 2 uses -> on-every-use
nil-assignment: 2 evaluations, 2 uses -> on-every-use
array-removal: 2 evaluations, 2 uses -> on-every-use
loop-iteration: 3 evaluations, 3 uses -> on-every-use
immediately: 0
on-first-use: 0
on-every-use: 4
never: 0
```


Start with the order of the `print` lines. The line `used scope-1` comes before `deinit scope-1`: in the measured run the instance was destroyed at the end of the scope, and the `deinit` line appeared on scope exit. With `nil` assignment, `deinit` runs inside the assignment, and the `after true` line that follows confirms it. The array holds two instances; `removeLast()` takes out the last one, so `array-2` is destroyed before `array-1`. In the loop, three iterations produce three separate `deinit` runs, and each one finishes before the next iteration.

All four `Probe` objects say `on-every-use`. The first three count two evaluations because there are two rounds, and the loop counts three because it has three rounds. The `deinit` body runs again every time an instance is destroyed, and every destruction belongs to a new instance. This lesson's moment is therefore **on every use**. In the `tally` output, `immediately`, `on-first-use` and `never` are zero.

#### The Function Boundary

References are not held only by variables; an instance passed to a function as a parameter is also alive for the duration of the call. The second measurement separates two cases. In one, a function produces the instance and the caller holds it. In the other, the produced instance is bound to no variable and lives only in the middle of an expression.

```swift
// main.swift — a reference at the function boundary
func inspect(_ session: Session) -> String {
    session.name
}

func make(_ name: String, owner: Probe) -> Session {
    Session(name, owner: owner)
}

let crossing = Probe("function-boundary")

for round in 1...2 {
    let made = make("made-\(round)", owner: crossing)
    _ = crossing.use { inspect(made) }
    print("round done \(round)")
}

for round in 1...2 {
    _ = crossing.use { inspect(make("transient-\(round)", owner: crossing)) }
    print("transient round done \(round)")
}

crossing.report()
```

```
round done 1
deinit made-1
round done 2
deinit made-2
deinit transient-1
transient round done 1
deinit transient-2
transient round done 2
function-boundary: 4 evaluations, 4 uses -> on-every-use
```

In the first loop, the line `round done 1` comes before `deinit made-1`. The instance is alive during the `inspect` call, and the call does not extend its lifetime; the owner of the instance is still the `made` constant, and `deinit` runs at the end of the iteration, as `made` leaves its scope. In the second loop, the instance produced by `make` is bound to no name. In the measured run the instance was released as the calling expression finished, and the line `deinit transient-1` appears before `transient round done 1`. Together the two loops record four evaluations and four uses for `function-boundary`. In other words, passing an instance to a function does not extend its lifetime; what extends it is storing the instance in a name or a property.

#### Chained Release

An instance can hold another instance in a property. In that case, destroying the outer instance also releases the last reference to the inner one. The third measurement builds two chains together: `Holder` holds a `Session`, and `Car` inherits from `Vehicle`, and both classes have a `deinit` body. The question is which `deinit` body runs first.

```swift
// main.swift — an instance in a property and a subclass chain
final class Holder {
    let name: String
    let child: Session

    init(_ name: String, owner: Probe) {
        self.name = name
        child = Session("child-\(name)", owner: owner)
    }

    deinit {
        print("deinit \(name)")
    }
}

class Vehicle {
    let owner: Probe

    init(owner: Probe) {
        self.owner = owner
    }

    deinit {
        print("deinit superclass")
        _ = owner.eval("super")
    }
}

final class Car: Vehicle {
    deinit {
        print("deinit subclass")
        _ = owner.eval("sub")
    }
}

let nested = Probe("property-instance")
let inherited = Probe("superclass-chain")

for round in 1...2 {
    var holder: Holder? = Holder("holder-\(round)", owner: nested)
    _ = nested.use { holder = nil }
}

for _ in 1...2 {
    var car: Car? = Car(owner: inherited)
    _ = inherited.use { car = nil }
}

nested.report()
inherited.report()
```

```
deinit holder-1
deinit child-holder-1
deinit holder-2
deinit child-holder-2
deinit subclass
deinit superclass
deinit subclass
deinit superclass
property-instance: 2 evaluations, 2 uses -> on-every-use
superclass-chain: 4 evaluations, 2 uses -> on-every-use
```

The output shows `deinit holder-1` first and then `deinit child-holder-1`: the outer instance's `deinit` body runs first, its properties are released as soon as that body finishes, and the inner instance's `deinit` follows. This is why the outer `deinit` body can still reach the inner instance. In the subclass chain, the subclass's `deinit` body runs first and the superclass's follows. `property-instance` counts two evaluations over two rounds, because only the inner `Session` calls it. `superclass-chain` sees two `eval` calls per round and so counts four evaluations over two rounds. Both say `on-every-use`: the number of evaluations can be greater than or equal to the number of uses, and the rule only looks at whether the expression ran more than once. `deinit` cannot be called explicitly and takes no parameters; it is run by the runtime exactly once, when the counter drops to zero.

#### Overwriting Releases the Old Value

Assigning `nil` is not the only form of release. Assigning a new instance to a `var` property also releases the reference to the old instance the property was holding. This measurement assigns a second `Session` to the `session` property of a `Slot` class and prints `evaluations` on both sides of the assignment. The new instance is bound to a separate `Probe`, so the counted `deinit` belongs only to the old instance.

```swift
// main.swift — overwriting a property
final class Slot {
    var session: Session?

    init(_ session: Session?) {
        self.session = session
    }
}

let overwritten = Probe("overwrite")
let spare = Probe("spare")

for round in 1...2 {
    let slot = Slot(Session("old-\(round)", owner: overwritten))
    print("before write \(overwritten.evaluations)")
    _ = overwritten.use { slot.session = Session("new-\(round)", owner: spare) }
    print("after write \(overwritten.evaluations)")
}

overwritten.report()
```

```
before write 0
deinit old-1
after write 1
deinit new-1
before write 1
deinit old-2
after write 2
deinit new-2
overwrite: 2 evaluations, 2 uses -> on-every-use
```

In each round, `deinit old-1` appears between the lines `before write 0` and `after write 1`: while the assignment places the new value, it releases the last strong reference to the old value, and the old instance is destroyed before the assignment completes. `deinit new-1` comes at the end of the round, because `slot` leaves its scope at that point and releases the instance inside it. So the same property held two separate instances in sequence during the round and produced two separate `deinit` runs. `overwrite` counts two evaluations over two rounds and says `on-every-use`. The rule has not changed: `deinit` is not tied to a release line, it is tied to the counter dropping to zero. Overwriting subtracts one from that counter, and so do `nil` assignment and scope end.

#### Bulk Clearing

The instances held by an array are not released one by one but as the array is emptied. This measurement builds two separate arrays and empties each with `removeAll()`. The question is how many `deinit` bodies a single call runs.

```swift
// main.swift — bulk release with removeAll
let cleared = Probe("bulk-clear")

for round in 1...2 {
    var batch = [
        Session("bulk-\(round)-a", owner: cleared),
        Session("bulk-\(round)-b", owner: cleared)
    ]
    print("before clear \(cleared.evaluations)")
    _ = cleared.use { batch.removeAll() }
    print("after clear \(cleared.evaluations), in array \(batch.count)")
}

cleared.report()
```

```
before clear 0
deinit bulk-1-a
deinit bulk-1-b
after clear 2, in array 0
before clear 2
deinit bulk-2-a
deinit bulk-2-b
after clear 4, in array 0
bulk-clear: 4 evaluations, 2 uses -> on-every-use
```

The `removeAll()` call is a single line, but because the array holds two instances, two `deinit` bodies run: between `before clear 0` and `after clear 2`, `deinit bulk-1-a` and `deinit bulk-1-b` appear. In the second round the counter goes from 2 to 4. Here `Probe` counts four evaluations for two uses and again says `on-every-use`; one call running several `deinit` bodies does not contradict the `on-every-use` rule, because the rule looks not at the number of evaluations but at whether the expression ran more than once. Each instance the array releases has its own counter. If one of them were also held by another variable, `removeAll()` would release only the array's share, and that instance's `deinit` would wait until its counter dropped to zero; the bounding measurement shows this case.

#### The Bounding Measurement

The rule above may give the impression that `deinit` runs at every release. The last measurement shows that this is wrong. Two variables, `first` and `second`, hold the same instance. First `first` is released, then `second`. `shared.evaluations` is read after each step.

```swift
// main.swift — a second reference and a top-level let
let shared = Probe("second-reference")
let outlives = Probe("top-level-let")

for round in 1...2 {
    var first: Session? = Session("shared-\(round)", owner: shared)
    var second = first
    _ = shared.use { first = nil }
    print("first released: \(shared.evaluations) deinit, second \(second == nil ? "absent" : "present")")
    _ = shared.use { second = nil }
    print("second released: \(shared.evaluations) deinit")
}

let pinned = Session("top-level", owner: outlives)
_ = outlives.use { pinned.name }
_ = outlives.use { pinned.name }

shared.report()
outlives.report()
```

```
first released: 0 deinit, second present
deinit shared-1
second released: 1 deinit
first released: 1 deinit, second present
deinit shared-2
second released: 2 deinit
second-reference: 2 evaluations, 4 uses -> on-every-use
top-level-let: 0 evaluations, 2 uses -> never
```

After the first release the `deinit` count is zero, and `second` still holds the instance. The line `deinit shared-1` appears only at the second release. The same sequence repeats in the second round. The counter reaching zero is the condition for `deinit` to run; the release line itself is not the condition. The `second-reference` `Probe` records two evaluations and four uses and says `on-every-use`, but it does not say this alone: which release triggers `deinit` can be seen only from the `print` order and the `evaluations` reads placed in between.

The last two lines show the second limit. `pinned`, held by a top-level `let`, is used twice, but the `top-level-let` `Probe` records zero evaluations and says `never`. A top-level `let` is held until the end of the process, and in this measurement `deinit` does not run at process end. The absence of `deinit` is not an error; the reference count never dropped to zero. Relying on the `deinit` body of such an instance to close a resource would be a mistake.

**MA1.** Only one instance was measured for each release path; that the rule also holds on other release paths was not shown in this lesson. Choosing four paths is a design choice.

#### Summary

- Class instances are managed by automatic reference counting (ARC); `deinit` runs at the moment the last strong reference is released.
- Scope end, `nil` assignment, array removal and loop iteration follow the same rule: `deinit` runs at the release point.
- A second strong reference postpones `deinit`; `deinit` does not run until the counter drops to zero.
- An instance held by a top-level `let` is not released until the end of the process, and in this measurement `deinit` does not run (`never`).
- This lesson's moment: **on every use**. The destruction of each new instance runs the `deinit` body again.

#### Next Step

In this lesson the counter had to drop to zero, and it did. If two classes hold each other strongly, the counter never drops to zero and neither `deinit` runs. The next lesson measures how `weak` and `unowned` break this cycle, and why the `deinit` body is never evaluated in it.

### Strong, Weak and Unowned References

Source: https://academia.sh/en/courses/swift/strong-weak-and-unowned-references

Measures that deinit never runs when two classes hold each other strongly, that weak and unowned break the cycle, and that an unowned reference cannot be read once its object is gone.

In the previous lesson the reference count dropped to zero and `deinit` ran. The count reaching zero was a condition, not a guarantee. If two class instances hold each other with **strong references**, each one keeps the other's counter one above zero, and both stay alive even when every outside name has been released. This situation is called a **retain cycle**. This lesson builds the cycle, breaks it in two ways, and measures when the `deinit` body runs in each.

There are two tools for breaking it. A **weak reference (`weak`)** does not hold the instance: it does not raise the counter, and it becomes `nil` on its own when the instance it points to is destroyed, so it is always an optional `var`. An **unowned reference (`unowned`)** also does not raise the counter, but it never becomes `nil` and does not have to be optional; in return it asks for a promise that the instance it points to will outlive the holder. `Probe` is given as in the previous lesson.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```


#### The Retain Cycle

The two measured classes are `Account` and `Profile`. The `deinit` body of each prints a line and notifies the shared `Probe` through `eval`. `Account` holds a `Profile`, and `Profile` holds an `Account`; both use the default, that is, strong, reference. In each round two instances are built, linked to each other, and then both are set to `nil`. The outside names are released this way.

```swift
// main.swift — two classes hold each other strongly
final class Account {
    let name: String
    let owner: Probe
    var profile: Profile?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit account \(name)")
        _ = owner.eval(name)
    }
}

final class Profile {
    let title: String
    let owner: Probe
    var account: Account?

    init(_ title: String, owner: Probe) {
        self.title = title
        self.owner = owner
    }

    deinit {
        print("deinit profile \(title)")
        _ = owner.eval(title)
    }
}

let cyclic = Probe("retain-cycle")

for round in 1...2 {
    var account: Account? = Account("account-\(round)", owner: cyclic)
    var profile: Profile? = Profile("profile-\(round)", owner: cyclic)
    account?.profile = profile
    profile?.account = account
    _ = cyclic.use {
        account = nil
        profile = nil
    }
    print("released \(round): \(cyclic.evaluations) deinit")
}

cyclic.report()
```

```
released 1: 0 deinit
released 2: 0 deinit
retain-cycle: 0 evaluations, 2 uses -> never
```

In both rounds the `deinit` count after the release is zero, and no `deinit` line ever appears. Because each instance is held by the other's property, both counters stay at one or higher. `retain-cycle` records two uses and zero evaluations, and the rule says `never`. This lesson's moment is therefore **never**: the `deinit` body is not evaluated at any moment. Nothing reports an error, either. The two instances in the cycle stay in memory until the end of the program.

#### Breaking It with a Weak Reference

To break the cycle, the reference on only one of the two sides is made weak. The second measurement defines the `Profile.account` property as `weak var` and changes nothing else. This time the instances are released in two steps: first `account`, then `profile`. After each step `profile?.account` is read and the `deinit` count is printed.

```swift
// main.swift — one side holds weakly
final class Account {
    let name: String
    let owner: Probe
    var profile: Profile?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit account \(name)")
        _ = owner.eval(name)
    }
}

final class Profile {
    let title: String
    let owner: Probe
    weak var account: Account?

    init(_ title: String, owner: Probe) {
        self.title = title
        self.owner = owner
    }

    deinit {
        print("deinit profile \(title)")
        _ = owner.eval(title)
    }
}

let broken = Probe("weak-reference")

for round in 1...2 {
    var account: Account? = Account("account-\(round)", owner: broken)
    var profile: Profile? = Profile("profile-\(round)", owner: broken)
    account?.profile = profile
    profile?.account = account
    print("linked: \(profile?.account == nil ? "nil" : "set")")
    _ = broken.use { account = nil }
    print("account released: \(profile?.account == nil ? "nil" : "set"), \(broken.evaluations) deinit")
    _ = broken.use { profile = nil }
    print("profile released: \(broken.evaluations) deinit")
}

broken.report()
```

```
linked: set
deinit account account-1
account released: nil, 1 deinit
deinit profile profile-1
profile released: 2 deinit
linked: set
deinit account account-2
account released: nil, 3 deinit
deinit profile profile-2
profile released: 4 deinit
weak-reference: 4 evaluations, 4 uses -> on-every-use
```

After linking, `profile?.account` is set. When the `account` name is released, no strong reference to the `Account` instance remains: because `profile.account` is weak, it had not raised the counter. The line `deinit account account-1` appears immediately, and the read that follows gives `nil`; a weak reference becomes `nil` on its own at the moment the instance it points to is destroyed. The `Profile` instance, on the other hand, is still held by the `profile` name, so it stays alive, and the `deinit profile` line appears only when that name is released. Four `deinit` bodies ran in two rounds, and `weak-reference` says `on-every-use`.

#### Breaking It with an Unowned Reference

A weak reference says that the instance may disappear. If a relationship does not run in that direction, that is, if a `Card` will never exist without a `Customer`, the reference is written as `unowned let`. The third measurement builds this relationship: `Customer` holds an optional `card`, and `Card` carries an `unowned let customer`. The customer holds the card, and the card does not hold the customer. The measurement releases only the customer name.

```swift
// main.swift — an unowned reference binds to the longer-lived side
final class Customer {
    let name: String
    let owner: Probe
    var card: Card?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit customer \(name)")
        _ = owner.eval(name)
    }
}

final class Card {
    let number: String
    let owner: Probe
    unowned let customer: Customer

    init(_ number: String, customer: Customer, owner: Probe) {
        self.number = number
        self.customer = customer
        self.owner = owner
    }

    deinit {
        print("deinit card \(number)")
        _ = owner.eval(number)
    }
}

let bound = Probe("unowned-reference")

for round in 1...2 {
    var customer: Customer? = Customer("customer-\(round)", owner: bound)
    if let current = customer {
        current.card = Card("card-\(round)", customer: current, owner: bound)
        print("card owner: \(current.card?.customer.name ?? "none")")
    }
    _ = bound.use { customer = nil }
    print("released \(round): \(bound.evaluations) deinit")
}

bound.report()
```

```
card owner: customer-1
deinit customer customer-1
deinit card card-1
released 1: 2 deinit
card owner: customer-2
deinit customer customer-2
deinit card card-2
released 2: 4 deinit
unowned-reference: 4 evaluations, 2 uses -> on-every-use
```

In every round the `deinit customer` line comes before the `deinit card` line. When the customer is released, its counter drops to zero, the `deinit` body runs, its properties are then released, and the card's only strong reference goes with them. What breaks the cycle in this chain is that the card does not hold the customer strongly; `unowned` expresses this without making the reference optional. `unowned-reference` records two uses and four evaluations, two `deinit` bodies run in every round, and the rule says `on-every-use`.

#### The Delegate Pattern

The most common place for a weak reference is the delegate pattern: an object stores a second object that it will notify when its work is finished, while the notified object already holds the object doing the work. Strong references in both directions would build a retain cycle. This measurement uses the `weak var delegate` property of the `Worker` class, and `Reporter` holds the `Worker` strongly. At the end of the round only the `reporter` name is released, and the `worker` name stays in hand.

```swift
// main.swift — the delegate is weak, the worker is strong
final class Reporter {
    let name: String
    let owner: Probe
    let worker: Worker

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
        worker = Worker()
        worker.delegate = self
    }

    deinit {
        print("deinit reporter \(name)")
        _ = owner.eval(name)
    }
}

final class Worker {
    weak var delegate: Reporter?
}

let handedOver = Probe("delegate")
for round in 1...2 {
    var reporter: Reporter? = Reporter("reporter-\(round)", owner: handedOver)
    let worker = reporter!.worker
    print("delegate \(worker.delegate?.name ?? "nil")")
    _ = handedOver.use { reporter = nil }
    print("released: delegate \(worker.delegate?.name ?? "nil"), \(handedOver.evaluations) deinit")
}

handedOver.report()
```

```
delegate reporter-1
deinit reporter reporter-1
released: delegate nil, 1 deinit
delegate reporter-2
deinit reporter reporter-2
released: delegate nil, 2 deinit
delegate: 2 evaluations, 2 uses -> on-every-use
```

After linking, `worker.delegate` gives the name of the reporter. When the `reporter` name is released, no strong reference to the `Reporter` instance remains: because `Worker` holds it weakly, it had not raised the counter. The line `deinit reporter reporter-1` appears immediately, and the read that follows gives `nil`. The `worker` keeps living because it is held by the `worker` name; although `Reporter` held it in a property, `Reporter` itself is gone, so the `Worker`'s only remaining share is the outside name. The pattern relies on this asymmetry: the notified object does not have to outlive the notifier, and the notifier learns that the notified object is gone by reading `nil`. This is why a delegate property is always written as an optional value and checked before every use. Two `deinit` bodies run in two rounds, and `delegate` says `on-every-use`.

#### Weak and Unowned Reads

As long as the instance they point to is alive, the two reference forms give the same value. The difference begins after the instance is gone. This measurement builds a `Watcher`: two properties, one a `weak var` and the other an `unowned let`, point to the same `Target` instance. While the instance is alive both are read; then the instance is released and only the weak property is read. The unowned property is not read after this point; the read would stop the program.

```swift
// main.swift — a weak and an unowned view of the same target
final class Target {
    let name: String
    let owner: Probe

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit target \(name)")
        _ = owner.eval(name)
    }
}

final class Watcher {
    weak var soft: Target?
    unowned let strict: Target

    init(_ target: Target) {
        soft = target
        strict = target
    }
}

let looked = Probe("weak-and-unowned")
for round in 1...2 {
    var target: Target? = Target("target-\(round)", owner: looked)
    let watcher = Watcher(target!)
    print("while alive: weak \(watcher.soft?.name ?? "nil"), unowned \(watcher.strict.name)")
    _ = looked.use { target = nil }
    print("after gone: weak \(watcher.soft?.name ?? "nil")")
}

looked.report()
```

```
while alive: weak target-1, unowned target-1
deinit target target-1
after gone: weak nil
while alive: weak target-2, unowned target-2
deinit target target-2
after gone: weak nil
weak-and-unowned: 2 evaluations, 2 uses -> on-every-use
```

While the instance is alive, both reads give `target-1`; at this moment the two forms cannot be told apart. After the line `deinit target target-1`, the weak read gives `nil`: once the instance is destroyed, a weak reference reads as `nil`. The unowned read is not measured at the same point: the `strict.name` line would read an instance that is gone, and the runtime would stop the program. The choice between the two forms is therefore not a choice of reading style but a promise about what must hold. If the target can go before the `watcher`, write weak; if that is impossible, write unowned. `weak-and-unowned` counts two evaluations in two rounds and says `on-every-use`; the result of the weak read is determined anew at every read. The result of an earlier read is not carried to a later one.

#### The Bounding Measurement

Weak and unowned references have only this in common: they do not hold what they point to. They part ways when read after the instance they point to is gone. A weak reference gives `nil`, and the second measurement above showed this. An unowned reference has no such guarantee: reaching an instance that is gone through `unowned` stops the program at run time. This is why that read is not measured. The fragment below is source only and is not run. It makes no output claim either.

```swift
// Source fragment: not run
var customer = Customer("customer-3", owner: bound)
let card = Card("card-3", customer: customer, owner: bound)
customer = Customer("customer-4", owner: bound)
print(card.customer.name)
```

The third line releases the last strong reference to `customer-3`; because `Card` does not hold it, the instance is destroyed. The fourth line reads an instance that has been destroyed. Had the same structure been written with `weak`, the read would have given `nil` and the program would have continued. The choice is therefore a lifetime promise: `unowned` is bound only to an instance that is certain to live longer than the instance carrying the reference; wherever there is doubt, `weak` is used. The compiler does not check this promise, so this is a limit, not a moment.

**MA2.** One class pair was measured for each linking form; all three pairs are small chains of two classes. That the same rule holds in longer cycles (three or more classes) was not shown in this lesson. Choosing the pairs is a design choice.

#### Summary

- If two classes hold each other strongly, their reference counts never drop to zero and neither `deinit` runs; this is a retain cycle.
- Making one side `weak var` breaks the cycle; a weak reference becomes `nil` when the instance it points to is destroyed.
- `unowned let` is bound to the side that lives longer and never becomes `nil`; reading an instance that has been destroyed stops the program, so it is not measured.
- This lesson's moment: **never**. In a retain cycle the `deinit` body is not evaluated at any moment; once the cycle is broken it runs in every round.

#### Next Step

In this lesson the cycle was built between two class properties. A closure stored in a class's own property can build the same cycle by capturing `self` strongly, and this is the most common form of retain cycle. The next lesson measures capturing in closures and when the `[weak self]` capture list is evaluated.

### Capturing in Closures

Source: https://academia.sh/en/courses/swift/capturing-in-closures

Measures that a closure stored in an object's own property blocks deinit when it captures self, that a weak self capture list resolves it, and that a capture list is evaluated once when the closure is created.

The previous lesson built a retain cycle between two class properties. The same cycle can be built through a **closure** that a class stores in its own property, and in practice this is the form met most often. A closure takes the outside values it uses in its body into itself; this is called **capturing**. If the body of the closure uses `self`, the closure captures the instance with a strong reference. If the instance also holds the closure in a property, the two sides hold each other.

This lesson builds the cycle once, breaks it with a `[weak self]` **capture list**, and then measures another property of the capture list: the expression inside the list is evaluated not on every call of the closure but once, while the closure is being created. At the end comes a measurement that draws the limit of the question: not every closure builds a cycle.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

#### When the Closure Holds the Instance

The `Button` class stores an optional closure named `onTap`. The `install` method assigns to this property a closure whose body reads `self.name`. In each round a `Button` is built, its closure is installed, it is called once, and the name is released.

```swift
// main.swift — a closure that captures self strongly blocks deinit
final class Button {
    let name: String
    let owner: Probe
    var onTap: (() -> Void)?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    func install() {
        onTap = { print("tapped \(self.name)") }
    }

    deinit {
        print("deinit button \(name)")
        _ = owner.eval(name)
    }
}

let trapped = Probe("closure-cycle")

for round in 1...2 {
    var button: Button? = Button("button-\(round)", owner: trapped)
    button?.install()
    button?.onTap?()
    _ = trapped.use { button = nil }
    print("released \(round): \(trapped.evaluations) deinit")
}

trapped.report()
```

```
tapped button-1
released 1: 0 deinit
tapped button-2
released 2: 0 deinit
closure-cycle: 0 evaluations, 2 uses -> never
```

The closure was called and the name was written, but after the release no `deinit` line ever appears. `Button` holds the closure through `onTap`, and the closure holds `Button` through `self`. When the outside name is gone, the counter drops to one, not to zero. The rule of the previous lesson holds here too: `closure-cycle` records two uses and zero evaluations, and its moment is `never`.

#### Breaking It with Weak Self

The fix is to put a capture list at the head of the closure. The `[weak self]` list gives the closure a weak copy of `self`; the closure no longer holds the instance, but once the instance is gone, `self` becomes optional and can be `nil`. The body therefore first checks with `guard let self` whether the instance is still alive. The measurement calls the closure twice: before the name is released and after. For the call after the release, the closure is saved in a separate variable.

```swift
// main.swift — [weak self] gets ahead of the cycle
final class Button {
    let name: String
    let owner: Probe
    var onTap: (() -> Void)?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    func install() {
        onTap = { [weak self] in
            guard let self else {
                print("button gone")
                return
            }
            print("tapped \(self.name)")
        }
    }

    deinit {
        print("deinit button \(name)")
        _ = owner.eval(name)
    }
}

let broken = Probe("weak-capture")

for round in 1...2 {
    var button: Button? = Button("button-\(round)", owner: broken)
    button?.install()
    let saved = button?.onTap
    saved?()
    _ = broken.use { button = nil }
    saved?()
    print("released \(round): \(broken.evaluations) deinit")
}

broken.report()
```

```
tapped button-1
deinit button button-1
button gone
released 1: 1 deinit
tapped button-2
deinit button button-2
button gone
released 2: 2 deinit
weak-capture: 2 evaluations, 2 uses -> on-every-use
```

This time the `deinit` line appears in every round right after the release. The closure did not hold `Button`, so when the outside name was gone, the counter dropped to zero. After the release the same closure can still be called, but `guard let self` fails and `button gone` is written. The closure now runs empty: the instance is gone, the closure remains. `weak-capture` records two uses and two evaluations; over the two rounds a `deinit` runs at every use, and its moment is `on-every-use`.

#### When a Capture List Is Evaluated

`[weak self]` is only one use of the capture list. A list can also hand the closure a value: each entry written in the form `[snapshot = expression]` is evaluated **once, while the closure is being created**, and becomes a fixed copy inside the closure. A variable captured without a list, on the other hand, is read with its current value on every call of the closure. The measurement below shows this difference with two `Probe` objects. First both closures are created while `level` is 1, then `level` becomes 5, and then each closure is called twice.

```swift
// main.swift — a capture list at creation, an unlisted read on every call
let listed = Probe("capture-list")
let live = Probe("no-capture-list")

do {
    var level = 1
    let withList = { [snapshot = listed.eval(level)] in snapshot }
    let withoutList = { live.eval(level) }
    level = 5
    print("listed: \(listed.use { withList() }) \(listed.use { withList() })")
    print("unlisted: \(live.use { withoutList() }) \(live.use { withoutList() })")
}

listed.report()
live.report()
```

```
listed: 1 1
unlisted: 5 5
capture-list: 1 evaluations, 2 uses -> immediately
no-capture-list: 2 evaluations, 2 uses -> on-every-use
```

The closure with the list returns 1 in both calls: the copy was taken while `level` was still 1, and the later assignment did not change it. The closure without the list returns 5 in both calls, because it reads the variable again on every call. The Probe output records these as two different moments. `capture-list` records a single evaluation, and because that evaluation happened before the first use, its moment is **immediately**. `no-capture-list` records two evaluations, so it is `on-every-use`. This lesson's moment is **immediately**: the expression in the capture list is evaluated once, at the point where the closure is created.

#### Two Closures Share a Variable

Capturing is often not the copying of a value but the sharing of a variable. Two closures that capture the same local variable look at the same box of that variable. This measurement builds an incrementing closure and a reading closure that capture a `total` variable. The incrementer makes an evaluation through `Probe` on every call, and the question is whether the reader sees the change made by the incrementer.

```swift
// main.swift — two closures capture the same variable
let shared = Probe("shared-variable")
do {
    var total = 0
    let add = { total += shared.eval(10) }
    let read = { total }
    print("start \(read())")
    shared.use { add() }
    print("first increase \(read())")
    shared.use { add() }
    print("second increase \(read())")
}
shared.report()
```

```
start 0
first increase 10
second increase 20
shared-variable: 2 evaluations, 2 uses -> on-every-use
```

The `read` closure sees the change made by the incrementer: `start 0`, then `first increase 10` and `second increase 20`. If the two closures held separate copies of the value of `total`, the reader would always give 0. The closures look at the same box, and every call that changes the box is visible to the other. `shared-variable` counts two evaluations in two uses and says `on-every-use`. The capture list of the previous section cuts this sharing: a closure written with `[total]` takes the value at that moment, not the variable. Sharing is the default; copying is a behavior that has to be asked for explicitly.

#### Escaping and Non-Escaping Closures

A closure can outlive the function that receives it. If it will, its parameter is marked `@escaping`; an unmarked closure has to finish before the function returns. These two forms are measured with `Probe`. The non-escaping closure is called immediately in the `run` function. The escaping closure is added to an array in the `store` function and is called only later. After two `store` calls, and before the closures are called, `later.evaluations` is read.

```swift
// main.swift — non-escaping evaluates now, escaping evaluates later
let now = Probe("non-escaping")
let later = Probe("escaping")
do {
    var pending: [() -> Int] = []

    func run(_ work: () -> Int) -> Int {
        work()
    }

    func store(_ work: @escaping () -> Int) {
        pending.append(work)
    }

    for round in 1...2 {
        _ = now.use { run { now.eval(round) } }
        store { later.eval(round) }
        print("round \(round): non-escaping \(now.evaluations), escaping \(later.evaluations)")
    }
    for work in pending {
        _ = later.use { work() }
    }
    print("escaping after calls \(later.evaluations)")
}
now.report()
later.report()
```

```
round 1: non-escaping 1, escaping 0
round 2: non-escaping 2, escaping 0
escaping after calls 2
non-escaping: 2 evaluations, 2 uses -> on-every-use
escaping: 2 evaluations, 2 uses -> on-every-use
```

In each round the `non-escaping` counter rises before `run` returns: 1 in the first round, 2 in the second. The `escaping` counter, on the other hand, is still 0 after both `store` calls, because `store` only adds the closure to the array and does not call it. The closures are called only in the next loop, and the counter becomes `escaping after calls 2`. Both `Probe` objects say `on-every-use`, but the place of the evaluation differs: the evaluation of the non-escaping closure is inside the call of the function that receives it. The evaluation of the escaping closure can come long after the line where the closure was created. This difference also explains why a closure forces `self` to be written explicitly: an escaping closure can outlive the instance it captures. A non-escaping closure can never hold the instance, because it ends when the function returns.

#### The Strong Temporary Copy

The `guard let self` line does not only check whether `self` is `nil`; it also sets up a strong temporary reference that lives through the body. This reference holds the instance until the closure ends. The measurement tests it as follows: the closure of a `Job` instance calls a function in the middle of its body that releases the outside name. Does `deinit` run at the release line, or after the body finishes?

```swift
// main.swift — guard let self holds the instance through the body
final class Job {
    let name: String
    let owner: Probe
    var run: (() -> Void)?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    func install(release: @escaping () -> Void) {
        run = { [weak self] in
            guard let self else {
                print("job gone")
                return
            }
            print("body started \(self.name)")
            release()
            print("body ending \(self.name)")
        }
    }

    deinit {
        print("deinit job \(name)")
        _ = owner.eval(name)
    }
}

let held = Probe("temporary-strong")
for round in 1...2 {
    var job: Job? = Job("job-\(round)", owner: held)
    job?.install { job = nil }
    let saved = job?.run
    _ = held.use { saved?() }
    print("closure returned: \(held.evaluations) deinit")
}
held.report()
```

```
body started job-1
body ending job-1
deinit job job-1
closure returned: 1 deinit
body started job-2
body ending job-2
deinit job job-2
closure returned: 2 deinit
temporary-strong: 2 evaluations, 2 uses -> on-every-use
```

In each round `release()` is called between the lines `body started` and `body ending`, and the outside `job` name becomes `nil`. Even so, the line `deinit job job-1` comes after the line `body ending job-1`. The temporary strong reference set up by `guard let self` keeps the instance up until the body ends; the last reference is released only as the closure returns. The line `closure returned: 1 deinit` confirms it: at the moment the closure returns, the counter is 1. `temporary-strong` counts two evaluations in two rounds and says `on-every-use`. The practical consequence runs in two directions. `[weak self]` keeps the closure from holding the instance permanently, but the instance does not disappear while the body is running. The work done in the body does not have to be split for fear that the instance will vanish.

#### The Bounding Measurement

Not every closure builds a cycle. For a cycle, the closure has to be **stored** in the instance. A closure that is created inside a method and finishes before the method returns, for example a closure given to a transformation of an array, is stored nowhere, and its capturing `self` does not hold the instance. The measurement shows this in a `Report` instance: the `joined` method reads the `name` property inside `parts.map { ... }`, the result is returned, and the instance is released.

```swift
// main.swift — a closure that is not stored builds no cycle
final class Report {
    let name: String
    let owner: Probe
    let parts = ["a", "b", "c"]

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    func joined() -> String {
        parts.map { "\($0)-\(name)" }.joined(separator: ",")
    }

    deinit {
        print("deinit report \(name)")
        _ = owner.eval(name)
    }
}

let passing = Probe("temporary-closure")

for round in 1...2 {
    var report: Report? = Report("report-\(round)", owner: passing)
    print(report?.joined() ?? "none")
    _ = passing.use { report = nil }
    print("released \(round): \(passing.evaluations) deinit")
}

passing.report()
```

```
a-report-1,b-report-1,c-report-1
deinit report report-1
released 1: 1 deinit
a-report-2,b-report-2,c-report-2
deinit report report-2
released 2: 2 deinit
temporary-closure: 2 evaluations, 2 uses -> on-every-use
```

In each round `deinit` runs at the moment of the release. The `map` closure read `self`, but the closure ended the moment the method returned; no reference to it remained. The leak does not come from capturing itself but from the capturing closure continuing to live in the instance. The only place that needs a capture list is a stored closure.

**MA3.** Every measured class stores its closure in a single property. That several stored closures, or an object that keeps its closure in an outside list, follow the same rules was not measured in this lesson. Having a single closure is a design choice.

#### Summary

- If a closure stored in a property captures `self` strongly, the instance and the closure hold each other and `deinit` never runs.
- The `[weak self]` capture list does not hold the instance; when the instance is gone, `self` is `nil` and `guard let self` makes the closure run empty.
- `[snapshot = expression]` in a capture list is evaluated once while the closure is created; a variable captured without a list is read with its current value on every call.
- A closure that is not stored, such as the ones inside `map`, builds no cycle even when it uses `self`.
- This lesson's moment: **immediately**. The expression in the capture list is evaluated once, at the point where the closure is created.

#### Next Step

In this lesson the closure was a box that took a value or an instance into itself and stored it. Property wrappers do something similar for a property itself: they move how a value is stored and read to a separate type. The next lesson measures when the `wrappedValue` getter runs and when the initial value of the wrapper is set up.

### Property Wrappers

Source: https://academia.sh/en/courses/swift/property-wrappers

Measures that the wrappedValue getter of a property wrapper runs on every access, that the initial value is set up once, and that a cached wrapper turns the moment into first use.

In the previous lesson a closure was a box that took a value into itself and stored it. A **property wrapper (`@propertyWrapper`)** builds a similar box for the property itself: how the value of the property is stored, and what happens when it is read or written, moves into a separate type, and the property is marked with the name of that type. The only required member of a wrapper type is `wrappedValue`; this member runs when the property is read and when it is written. The optional `projectedValue` member offers a second value that is reached by putting `$` in front of the property name.

This lesson writes a wrapper and measures three different moments of it: the moment the getter runs, the moment the initial value is evaluated, and the moment that changes when a cache is added. Most of the measurements use a `Clamped` wrapper, a small type that squeezes a value into a range.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

```swift
// Clamped.swift — squeezes a value into a range
@propertyWrapper
struct Clamped {
    private var current: Int
    let range: ClosedRange<Int>
    let owner: Probe

    init(wrappedValue: Int, _ range: ClosedRange<Int>, owner: Probe) {
        self.range = range
        self.owner = owner
        self.current = min(max(wrappedValue, range.lowerBound), range.upperBound)
    }

    var wrappedValue: Int {
        get { owner.eval(current) }
        set { current = min(max(newValue, range.lowerBound), range.upperBound) }
    }

    var projectedValue: Bool { current == range.upperBound }
}
```

#### Writing the Wrapper

The `Clamped` wrapper holds an `Int` and squeezes the assigned value into the given range. The body of the `wrappedValue` getter calls `owner.eval` before it returns the value; every run of the getter is recorded this way. `projectedValue` is a `Bool` that says whether the value is at the upper bound, and it does not call `eval` when it is read, because what is measured is `wrappedValue`.

#### The Getter Runs on Every Access

When the wrapper is used, the property is written as `@Clamped(0...10, owner: reads) var level = 5`: the values in parentheses go to the `init` method of the wrapper, and `= 5` goes to the `wrappedValue` parameter. The first measurement reads `level` twice and assigns a value outside the range in between. In the last line, `$level` reads the projected value.

```swift
// main.swift — the wrappedValue getter runs on every access
let reads = Probe("wrapper-read")

do {
    @Clamped(0...10, owner: reads) var level = 5
    print("level: \(reads.use { level })")
    level = 42
    print("level: \(reads.use { level })")
    print("at upper bound: \($level)")
}

reads.report()
```

```
level: 5
level: 10
at upper bound: true
wrapper-read: 2 evaluations, 2 uses -> on-every-use
```

The first read gives 5 and the second gives 10: the assigned 42 was squeezed to the upper bound of the range. `$level` reads `projectedValue`, and because the value is at the upper bound it writes `true`. `wrapper-read` records two uses and two evaluations; because the getter runs on every access, its moment is `on-every-use`. The `$level` read did not raise the record, because it calls a different member. This lesson's moment is **on every use**.

#### The Initial Value Is Set Up Once

The `= 5` written on the property is evaluated not on every run of the getter but once, while the property is set up. The second measurement wraps the initial value in `start.eval(5)` and reads the property twice. The getter's own `eval` call writes to a different `Probe`, `quiet`, so `start` keeps the record of the initial value only.

```swift
// main.swift — the initial value is evaluated once while the property is set up
let start = Probe("initial-value")
let quiet = Probe("quiet-read")

do {
    @Clamped(0...10, owner: quiet) var level = start.eval(5)
    print("level: \(start.use { level }) \(start.use { level })")
}

start.report()
```

```
level: 5 5
initial-value: 1 evaluations, 2 uses -> immediately
```

Both reads give 5, and `initial-value` records a single evaluation. Because this evaluation happened before the first `use` call, its moment is `immediately`. The getter ran twice, but it did not evaluate the initial expression again: the `init` method of the wrapper took the value of the expression once and wrote it to `current`.

```swift
// Cached.swift — computes the value on first read and stores it
@propertyWrapper
final class Cached {
    private var memo: Int?
    private let make: () -> Int

    init(wrappedValue make: @autoclosure @escaping () -> Int) {
        self.make = make
    }

    var wrappedValue: Int {
        if let memo { return memo }
        let result = make()
        memo = result
        return result
    }
}
```

#### The Setter Runs on Every Assignment Too

`wrappedValue` works in both directions: `get` runs on a read, and `set` runs on an assignment. The initial value, on the other hand, does not pass through `set`; the `init` method stores it directly. This difference can be measured separately on the write side. The `Counted` wrapper calls `owner.eval` in the `set` body and applies no limit. The measurement starts the property at 0 and then increases it three times.

```swift
// Counted.swift — records every assignment
@propertyWrapper
struct Counted {
    private var current: Int
    let owner: Probe

    init(wrappedValue: Int, owner: Probe) {
        self.current = wrappedValue
        self.owner = owner
    }

    var wrappedValue: Int {
        get { current }
        set { current = owner.eval(newValue) }
    }
}
```

```swift
// main.swift — set runs on every assignment, the initial value skips set
let writes = Probe("wrapper-write")

do {
    @Counted(owner: writes) var score = 0
    for amount in 1...3 {
        _ = writes.use { score += amount }
    }
    print("score: \(score)")
}

writes.report()
```

```
score: 6
wrapper-write: 3 evaluations, 3 uses -> on-every-use
```

The score is 6, because 1, 2 and 3 were added. `wrapper-write` records three uses and three evaluations: the initial `= 0` assignment did not enter the evaluation count, only the three increases did. The read and write sides follow the same rule: a member of the wrapper runs on every access, while the initial value is taken once in the `init` method.

#### The Projected Value

`Clamped` offers two things: the property itself through `wrappedValue`, and an extra piece of information carried beside it through `projectedValue`. The extra information is reached by putting `$` in front of the property name. This `$` read does not call the `wrappedValue` getter; it is a separate member. The measurement builds two identical wrappers with separate `Probe` objects and assigns both a value outside the range. It reads one through `$` and the other directly.

```swift
// main.swift — a $ read does not call the wrappedValue getter
let projected = Probe("projected-value")
let plain = Probe("direct-read")
do {
    @Clamped(0...10, owner: projected) var left = 5
    @Clamped(0...10, owner: plain) var right = 5
    left = 50
    right = 50
    print("at upper bound: \(projected.use { $left }) \(projected.use { $left })")
    print("value: \(plain.use { right }) \(plain.use { right })")
}
projected.report()
plain.report()
```

```
at upper bound: true true
value: 10 10
projected-value: 0 evaluations, 2 uses -> never
direct-read: 2 evaluations, 2 uses -> on-every-use
```

Both properties were assigned 50, and both were squeezed to 10. The `$left` read gives `true`: the value is at the upper bound. But this read does not go through the `wrappedValue` getter. `projected-value` records zero evaluations against two uses and says `never`, because there is no `eval` in the body of `projectedValue` and `current` is compared directly. `direct-read` records two evaluations in the same two uses and says `on-every-use`. A `$` read does not run the `wrappedValue` getter; it is a separate member: the `$` spelling asks the wrapper a question that is independent of the side effects of the `wrappedValue` getter. The moment question is therefore asked separately for each access: `left` and `right` are the same wrapper type, but which getter runs depends on how the access is written.

#### Wrapper Arguments Are Evaluated Once

The expressions in parentheses in `@Clamped(0...10, owner: quiet)` go to the `init` method of the wrapper. The compiler turns the line `@Clamped(...) var level = 5`, roughly, into a call `Clamped(wrappedValue: 5, 0...10, owner: quiet)` that runs once while the property is set up. This measurement tests both the property form and a hand-written `init` call. The upper bound of the range and the initial value pass through `Probe`.

```swift
// main.swift — wrapper arguments are evaluated once while the property is set up
let ceiling = Probe("range-argument")
let explicit = Probe("explicit-init")
let quiet = Probe("quiet")
do {
    @Clamped(0...ceiling.eval(10), owner: quiet) var level = 5
    print("level: \(ceiling.use { level }) \(ceiling.use { level })")

    let wrapper = Clamped(wrappedValue: explicit.eval(5), 0...10, owner: quiet)
    print("explicit: \(explicit.use { wrapper.wrappedValue }) \(explicit.use { wrapper.wrappedValue })")
}
ceiling.report()
explicit.report()
```

```
level: 5 5
explicit: 5 5
range-argument: 1 evaluations, 2 uses -> immediately
explicit-init: 1 evaluations, 2 uses -> immediately
```

On both paths the counter says the same thing. `range-argument` records a single evaluation, and because that evaluation happened before the first `use` call, its moment is `immediately`. The two reads did not recompute the upper bound of the range: `ceiling.eval(10)` ran once while the property was set up, and the `ClosedRange` value stayed inside the wrapper. The hand-written call `Clamped(wrappedValue: explicit.eval(5), ...)` gives the same result: `explicit-init` records a single evaluation and says `immediately`. The wrapper syntax introduces no new evaluation rule; it is a short way of writing an `init` call, and the arguments of the call are evaluated once at the moment of the call, as always. How many times the getter runs and how many times the argument is evaluated are two separate numbers: the first rises with every access, and the second is fixed once while the property is set up. This distinction requires choosing, from the start, which number is being looked at when a wrapper is read.

#### Composing Wrappers

More than one wrapper can be written on a property. The one on the left is outer, and the one on the right is inner. The `Traced` below is a generic wrapper; it stores the value as it is and calls `owner.eval` on every read. The measurement puts it outside `Clamped`. It reads the property twice and looks at how many times the getter of each layer runs.

```swift
// Traced.swift — a generic wrapper that records every read
@propertyWrapper
struct Traced<Value> {
    private var current: Value
    let owner: Probe

    init(wrappedValue: Value, owner: Probe) {
        self.current = wrappedValue
        self.owner = owner
    }

    var wrappedValue: Value {
        get { owner.eval(current) }
        set { current = newValue }
    }
}
```

```swift
// main.swift — two wrappers stacked
let outer = Probe("outer-wrapper")
let inner = Probe("inner-wrapper")
do {
    @Traced(owner: outer) @Clamped(0...10, owner: inner) var level = 50
    print("read: \(outer.use { inner.use { level } }) \(outer.use { inner.use { level } })")
    level = 3
    print("after write: \(outer.use { inner.use { level } })")
}
outer.report()
inner.report()
```

```
read: 10 10
after write: 3
outer-wrapper: 4 evaluations, 3 uses -> on-every-use
inner-wrapper: 3 evaluations, 3 uses -> on-every-use
```

The first two reads give 10: the initial value was 50, and the innermost `Clamped` had squeezed it to 10 inside `init`. After the assignment `level = 3`, the read gives 3. The counters are worth noting: the getter of the inner wrapper runs three times in three reads. The getter of the outer wrapper runs four times: three reads and the assignment itself. The assignment calls the outer getter one more time, because the outer wrapper first reads its value and then changes it on the inner `Clamped`. Composition therefore counts the number of runs of each of the two layers separately. Both `Probe` objects say `on-every-use`. Adding a layer adds a chain of `get` and `set` to every read and write. When a wrapper whose getter has side effects is placed in a composition, this extra work has to be taken into account. In this measurement the outer getter ran four times and the inner getter three times; compositions with more layers were not measured.

#### The Bounding Measurement

That the initial value is `immediately` is a result of how `Clamped` is written, not of the wrapper syntax. The `Cached` wrapper below turns the expression given to the `init` method into a closure with `@autoclosure` and does not call it until `wrappedValue` is first read. The result is stored in a property; later reads return the stored value. The same `@` sign and the same `= expression` spelling, but the evaluation moment has changed.

```swift
// main.swift — a cached wrapper turns the moment into first use
let lazyValue = Probe("cached-wrapper")

do {
    @Cached var total = lazyValue.eval(7)
    print("total: \(lazyValue.use { total }) \(lazyValue.use { total })")
}

lazyValue.report()
```

```
total: 7 7
cached-wrapper: 1 evaluations, 2 uses -> on-first-use
```

Both reads give 7. `cached-wrapper` records a single evaluation, but this time the evaluation happened inside the first `use` call, so its moment is `on-first-use`. The `@Cached` spelling looked like the `@Clamped` spelling; what makes the difference is whether the expression is used at once in the `init` method of the wrapper or held back in a closure. The moment is written in the body of the wrapper, not in the `@` syntax.

**MA4.** Both measured wrappers hold an `Int` value. That generic wrappers and wrappers used as class properties follow the same rules was not measured in this lesson. Use as a local variable is a design choice.

#### Summary

- A property wrapper is marked with `@propertyWrapper`; `wrappedValue` runs when the property is read and written, and `projectedValue` is read with the `$` prefix.
- The `wrappedValue` getter runs on every access; an assignment is carried out by the rule of the wrapper, for example by squeezing into a range.
- The initial value written on the property is evaluated once while the property is set up, in a wrapper such as `Clamped`.
- `Cached`, written with `@autoclosure` and a stored result, turns the same spelling into a single evaluation on first use; the moment is in the body of the wrapper.
- This lesson's moment: **on every use**. The `wrappedValue` getter runs on every access.

#### Next Step

In this lesson a wrapper moved the value rule of a property into a separate type. Result builders apply the same idea to a list of expressions: instead of being evaluated one by one, the lines in a block are given to methods of a builder type such as `buildBlock`, and that type decides which line runs at which moment. The next lesson writes a result builder of its own and measures that the expressions of the branch that is not chosen are never evaluated.

### Result Builders

Source: https://academia.sh/en/courses/swift/result-builders

Writes a result builder of its own and measures that expressions in an unchosen if or else branch are never evaluated, that a for loop evaluates every element, and that the branch is chosen at run time and not at compile time.

The previous lesson moved the value rule of a property into a separate type. A **result builder (`@resultBuilder`)** applies the same idea to a list of expressions. Expressions written one under another in the body of a closure normally run one by one and their values are discarded. In a closure passed to a parameter marked with a result builder, each line is instead given to a method of the builder type, and the values those methods return are combined into a single result. Which method each line is bound to, and how, decides at which moment the line runs.

This lesson writes a small builder that builds a list of strings and measures three things: whether an expression in an unchosen `if` branch is evaluated, how a `for` loop processes its elements, and when the choice of branch is made. The transformation itself happens at compile time and is not visible at run time; what is measured is the run-time behavior of the transformed code. This split between compile time and run time was covered separately in an earlier curriculum.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

```swift
// ListBuilder.swift — a result builder that builds a list of strings
@resultBuilder
struct ListBuilder {
    static func buildExpression(_ line: String) -> [String] {
        [line]
    }

    static func buildBlock(_ parts: [String]...) -> [String] {
        parts.flatMap { $0 }
    }

    static func buildOptional(_ part: [String]?) -> [String] {
        part ?? []
    }

    static func buildEither(first part: [String]) -> [String] {
        part
    }

    static func buildEither(second part: [String]) -> [String] {
        part
    }

    static func buildArray(_ parts: [[String]]) -> [String] {
        parts.flatMap { $0 }
    }
}

func makeList(@ListBuilder _ content: () -> [String]) -> [String] {
    content()
}
```

#### Writing the Builder

`ListBuilder` carries six static methods. `buildExpression` turns each single expression into a list of strings. `buildBlock` joins the parts of a block one after another. `buildOptional` handles the result of an `if` that has no `else` branch; if the branch is not chosen, it gives an empty list. `buildEither(first:)` and `buildEither(second:)` handle whichever of the `if` and `else` branches was chosen. `buildArray` joins the parts that come from each iteration of a `for` loop. `makeList` is a helper function that takes its closure as a parameter marked with `ListBuilder`.

#### The Unchosen Branch Is Not Evaluated

The first measurement writes two expressions inside `if`/`else`. One calls a `Probe` named `chosen`, the other a `Probe` named `skipped`. The condition is always true, so only the first branch is chosen. The `render` function is called twice.

```swift
// main.swift — the expression in the unchosen branch is not evaluated
let chosen = Probe("chosen-branch")
let skipped = Probe("skipped-branch")

do {
    let useFirst = true

    func render() -> [String] {
        makeList {
            "title"
            if useFirst {
                chosen.eval("first")
            } else {
                skipped.eval("second")
            }
        }
    }

    for _ in 1...2 {
        let lines = chosen.use { skipped.use { render() } }
        print(lines.joined(separator: ","))
    }
}

chosen.report()
skipped.report()
```

```
title,first
title,first
chosen-branch: 2 evaluations, 2 uses -> on-every-use
skipped-branch: 0 evaluations, 2 uses -> never
```

In both calls the list is `title,first`. `chosen-branch` records two evaluations, because the body of the builder runs again on every `render` call. `skipped-branch` sees two uses but zero evaluations: the expression of the second branch never runs. The rule says `never`. This lesson's moment is **never**: the expression of an unchosen branch is not evaluated at any moment. Merely being written does not call the expression.

#### The Loop Evaluates Every Element

A `for` loop is combined with `buildArray`, and the expression in its body is evaluated once for each element. The measurement processes an array of three elements twice and adds to the same closure a line that contains an `if`; that line goes through the `buildOptional` path.

```swift
// main.swift — for evaluates every element
let items = Probe("loop-item")

do {
    func render(names: [String]) -> [String] {
        makeList {
            for name in names {
                items.eval(name)
            }
            if names.count > 2 {
                "long list"
            }
        }
    }

    for _ in 1...2 {
        let lines = items.use { render(names: ["a", "b", "c"]) }
        print(lines.joined(separator: ","))
    }
}

items.report()
```

```
a,b,c,long list
a,b,c,long list
loop-item: 6 evaluations, 2 uses -> on-every-use
```

On every call the list is `a,b,c,long list`. `loop-item` records six evaluations: three elements in each of two calls. The elements were not cached once; the body of the builder runs again from the start on every call, and the loop processes every element again. Its moment is `on-every-use`. The string of the line `if names.count > 2` did not pass through a `Probe`; it only appeared in the list.

#### Expression Conversion

`buildExpression` converts each single expression of the block into the part type of the builder. If more than one `buildExpression` is written under the same name, the compiler picks the one that matches the type of the expression. The `MixedBuilder` below accepts both `String` and `Int`; it turns numbers into a string of the form `number 42`. The measurement passes the two expressions through separate `Probe` objects and looks at how many times each expression is evaluated on every call.

```swift
// MixedBuilder.swift — a result builder that accepts text and number expressions
@resultBuilder
struct MixedBuilder {
    static func buildExpression(_ line: String) -> [String] {
        [line]
    }

    static func buildExpression(_ number: Int) -> [String] {
        ["number \(number)"]
    }

    static func buildBlock(_ parts: [String]...) -> [String] {
        parts.flatMap { $0 }
    }
}

func makeMixed(@MixedBuilder _ content: () -> [String]) -> [String] {
    content()
}
```

```swift
// main.swift — buildExpression converts the expression, it does not re-evaluate it
let texts = Probe("text-expression")
let numbers = Probe("number-expression")
do {
    for _ in 1...2 {
        let lines = texts.use {
            numbers.use {
                makeMixed {
                    texts.eval("title")
                    numbers.eval(42)
                }
            }
        }
        print(lines.joined(separator: ","))
    }
}
texts.report()
numbers.report()
```

```
title,number 42
title,number 42
text-expression: 2 evaluations, 2 uses -> on-every-use
number-expression: 2 evaluations, 2 uses -> on-every-use
```

The output is `title,number 42` in both calls: the string expression passed as it was, and the integer expression was converted into the form `number 42`. Which path did the conversion is clear from the type of the expression; no separation was written in the builder. The counters show that the conversion did not change the evaluation. `text-expression` and `number-expression` record two evaluations each across the two calls and say `on-every-use`. `buildExpression` takes the result of the expression; it does not run the expression again. The builder runs the body of the closure from the start once per call, and each expression is evaluated exactly once. So when writing a conversion there is no need to worry that an expression with side effects will be repeated. Writing more than one `buildExpression` under the same name widens the expression types the builder accepts; an expression whose type is not covered gives a compile error, and it is not silently skipped at run time.

#### Nested Conditions

An `if` inside an `if` opens two nested `buildOptional` paths in the builder. If the outer condition does not hold, the inner condition itself is not evaluated either. The measurement runs the same closure twice with `visible: false`, then twice with `visible: true`. In each case there is a separate `Probe` for the inner condition and for the expression of the inner line.

```swift
// main.swift — if the outer condition does not hold, the inner condition is not evaluated
let closedGate = Probe("closed-inner-condition")
let closedHit = Probe("closed-inner-line")
let openGate = Probe("open-inner-condition")
let openHit = Probe("open-inner-line")
do {
    func render(visible: Bool, gate: Probe, hit: Probe) -> [String] {
        makeList {
            if visible {
                if gate.eval(true) {
                    hit.eval("inner")
                }
            }
        }
    }

    for _ in 1...2 {
        let shut = closedHit.use { closedGate.use { render(visible: false, gate: closedGate, hit: closedHit) } }
        let shown = openHit.use { openGate.use { render(visible: true, gate: openGate, hit: openHit) } }
        print("closed \(shut.count), open \(shown.count)")
    }
}
for probe in [closedGate, closedHit, openGate, openHit] {
    probe.report()
}
```

```
closed 0, open 1
closed 0, open 1
closed-inner-condition: 0 evaluations, 2 uses -> never
closed-inner-line: 0 evaluations, 2 uses -> never
open-inner-condition: 2 evaluations, 2 uses -> on-every-use
open-inner-line: 2 evaluations, 2 uses -> on-every-use
```

When the outer condition is `false`, neither the inner condition nor the inner line is evaluated. `closed-inner-condition` and `closed-inner-line` record zero evaluations against two uses each and say `never`; the `closed 0` line in the output also shows that the list stayed empty. When the outer condition is `true`, both inner expressions are evaluated once on every call: `open-inner-condition` and `open-inner-line` record two evaluations each and say `on-every-use`. The `open 1` line confirms that the inner line entered the list. The order of the conditions behaves like short-circuiting here as well: the next expression is evaluated only if the path of the previous one is open. The difference is that this comes not from the `&&` operator but from the `buildOptional` path of the builder. Each `if` produces its own `buildOptional` call; if the part of the outer call is empty, the inner one is never reached, and the inner expression stays `never` for that reason.

#### The Empty Loop

`buildArray` takes the parts that come from each iteration of the loop. If the loop never runs, the list of parts is empty and `buildArray` produces an empty list. The question is whether the expression in the body of a loop built over an empty array is evaluated. The measurement runs the same closure once with an empty array and once with a filled one.

```swift
// main.swift — the loop body over an empty array is not evaluated
let emptyLoop = Probe("empty-loop")
let filledLoop = Probe("filled-loop")
do {
    func render(names: [String], probe: Probe) -> [String] {
        makeList {
            for name in names {
                probe.eval(name)
            }
        }
    }

    for _ in 1...2 {
        let none = emptyLoop.use { render(names: [], probe: emptyLoop) }
        let some = filledLoop.use { render(names: ["x", "y"], probe: filledLoop) }
        print("empty \(none.count), filled \(some.count)")
    }
}
emptyLoop.report()
filledLoop.report()
```

```
empty 0, filled 2
empty 0, filled 2
empty-loop: 0 evaluations, 2 uses -> never
filled-loop: 4 evaluations, 2 uses -> on-every-use
```

In the loop over the empty array, the expression of the body never runs: `empty-loop` records zero evaluations against two uses and says `never`. The `empty 0` line says the result is an empty list as well; `buildArray` turns an empty list of parts into an empty result and gives no error. In the filled array each call processes two elements, so `filled-loop` records four evaluations over two calls and says `on-every-use`. The number of evaluations equals the number of iterations of the loop. For someone who builds a loop in the body of a builder, this is a measure: a loop that processes elements with an expression that has side effects runs as many times as there are elements on every call. The collection is not kept between calls; if the repetition of the side effect is not needed, the loop is moved outside the builder and the result is given to the builder ready-made.

The shared lesson of these measurements is this: the builder turns each line of the body into a call, and the way it is written decides which call is made. Instead of predicting by reading whether an expression will be evaluated, the transformation has to be unfolded in the mind: an expression becomes a `buildExpression` call, a condition becomes a `buildOptional` call (`buildEither` if there is an `else`), and a loop becomes a `buildArray` call. Before putting an expression with side effects into the body, the question is asked how many times and under which condition it will run in this chain of calls.

#### The Bounding Measurement

The transformation is done at compile time, but which branch is chosen is decided at run time. In the previous measurements the condition was fixed and this difference was not visible. The last measurement turns the condition into a parameter and calls `render` in turn with `true`, `false` and `true`. The expression of each branch is written to a separate `Probe`.

```swift
// main.swift — the branch is chosen at run time
let left = Probe("left-branch")
let right = Probe("right-branch")

do {
    func render(first: Bool) -> [String] {
        makeList {
            if first {
                left.eval("left")
            } else {
                right.eval("right")
            }
        }
    }

    for flag in [true, false, true] {
        let lines = left.use { right.use { render(first: flag) } }
        print(lines.joined(separator: ","))
    }
}

left.report()
right.report()
```

```
left
right
left
left-branch: 2 evaluations, 3 uses -> on-every-use
right-branch: 1 evaluations, 3 uses -> on-first-use
```

The calls write `left`, `right`, `left` in turn. `left-branch` records two evaluations: it runs only in the two calls that come with `true`. `right-branch` records a single evaluation, and because this evaluation happened in the second call, after the first use, the rule says `on-first-use`. An expression is evaluated in the call in which its branch is chosen; being written in the code means nothing on its own. For this reason the `never` moment holds only when the branch is never chosen, and it depends on the condition.

**MA5.** The measured builder only builds a list of strings, and extra methods such as `buildLimitedAvailability` were not defined. That the same rule holds for `if`/`else if` chains with two or three branches was not measured. Using a single builder type is a design choice.

#### Summary

- A result builder combines the expressions in a closure body into a result with the methods `buildBlock`, `buildExpression`, `buildOptional`, `buildEither` and `buildArray`.
- An expression in an unchosen branch of `if`/`else` is never evaluated; being written does not call it.
- The body of the builder runs again from the start on every call, and a `for` loop evaluates every element on every call.
- The transformation is done at compile time, but which branch is chosen is decided at run time; the `never` moment holds only if the branch is never chosen.
- This lesson's moment: **never**. The expression of an unchosen branch is not evaluated at any moment.

#### Next Step

The first lessons of this topic measured memory and evaluation moments in code that runs in a single flow. New questions appear when several jobs touch the same memory at the same time: whose control a value is under, and who reaches it and when. The next lesson covers actors, `Sendable`, which stands for a type that can be passed across boundaries, and `@MainActor`; it measures how the lazy property of an actor behaves on first access, and the work started with `async let`.

### Concurrency Safety

Source: https://academia.sh/en/courses/swift/concurrency-safety

Measures that the lazy property of an actor is set up once under concurrent reads and that an async let whose result is never awaited is still evaluated; covers the Sendable and @MainActor boundaries and closes the course.

The previous lessons measured the evaluation moments of code that runs in a single flow. When several jobs touch the same memory at the same time, another question arises: what happens if a value is written from two places at once. This is called a **data race**, and its result cannot be predicted. Swift 6 does not leave this question to run time; **strict concurrency checking** rejects code that could lead to a race at compile time.

This lesson describes three tools and measures two things. The tools are actor isolation, `Sendable` and `@MainActor`. The measurements are when the lazy property of an actor is set up and when the work started with `async let` runs. The counters inside the actor are plain `Int` values: `Probe` is a class, it is not `Sendable`, and it cannot cross the actor boundary. Because the order in which tasks run is undefined, the results are collected, sorted and then printed; only numbers are printed.

```swift
// Probe.swift — records when an expression is evaluated
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "never" }
        if evaluations > 1 { return "on-every-use" }
        return evaluatedBeforeUse ? "immediately" : "on-first-use"
    }

    func report() {
        print("\(label): \(evaluations) evaluations, \(uses) uses -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["immediately", "on-first-use", "on-every-use", "never"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

#### Actor Isolation

An **actor** is a type that keeps its state inside itself and allows only one task at a time to touch that state. It resembles a class, but its mutable state and isolated methods cannot be reached from outside without writing `await`; immutable `let` properties and `nonisolated` members are the exception. When a task outside calls a method of the actor, it writes `await`: the call enters the actor's queue, and if the actor is busy at that moment, the task waits. This waiting point is called a **suspension point**, and the mutable state of the actor cannot be reached without writing `await`.

The actor below keeps two counters and carries a lazy property named `total`. The expression of the property calls a method; the method counts in `builds` how many times it ran.

```swift
// Ledger.swift — an actor with a lazy property
actor Ledger {
    private(set) var builds = 0
    private(set) var reads = 0
    lazy var total: Int = makeTotal()

    private func makeTotal() -> Int {
        builds += 1
        return 42
    }

    func read() -> Int {
        reads += 1
        return total
    }
}
```

The measurement first looks at the counters without touching the property, then starts four tasks that call `read` at the same time.

```swift
// main.swift — a lazy property in an actor is set up once under concurrent reads
let ledger = Ledger()
print("builds before \(await ledger.builds)")

let values = await withTaskGroup(of: Int.self) { group in
    for _ in 1...4 {
        group.addTask { await ledger.read() }
    }
    var all: [Int] = []
    for await value in group {
        all.append(value)
    }
    return all
}

print(values.sorted())
print("reads \(await ledger.reads), builds \(await ledger.builds)")
```

```
builds before 0
[42, 42, 42, 42]
reads 4, builds 1
```

Four tasks read the same property, but the setup happened once. Before the property was touched, the build count was zero: the lazy expression ran not on the line where it is defined but on the first read. Actor isolation does two jobs here at once. It queues the reads and does not let the second begin before the setup of the first has finished. So it is impossible for two tasks to run the lazy expression at the same time and corrupt the counter. This lesson's moment is **on first use**.

It is worth stating what this measurement does not say. An actor does not stop jobs from running at the same time; it only queues the part that touches the state of the actor. The four tasks start at the same time, but they enter the `read` method one by one. The single setup of the lazy property is a direct result of this ordering: when the second task enters, the property is already set up.

A suspension point has a cost. While an actor method waits for other work with `await`, the actor becomes free and the next task can enter. For this reason, a value read before `await` is not assumed to stay the same afterwards. Isolation prevents two tasks from being inside at the same time; it does not guarantee that the state will not change while waiting. The methods in this lesson's measurements contain no `await`, so this case was not measured.

#### The Transferable Type and the Main Actor

If a value travels between tasks, it is crossing an isolation boundary. Types that can cross the boundary are called **`Sendable`**; in plain terms, a type that can be transferred. Numbers, strings and non-public value types that store only transferable types carry this property automatically; in public types the conformance is written explicitly. Actors carry it too, because they already protect their own insides. An ordinary class that holds mutable state does not: two tasks could write to the same instance at the same time.

For this reason `Probe` cannot cross an actor boundary. The fragment below is source only and is not run: a `Probe` is captured by the closure of another task. Swift 6 rejects this at compile time; the error text is not printed here.

```swift
// Source fragment: not run
let moved = Probe("moved")
let work = Task.detached { moved.eval(1) }
print(await work.value)
```

Why it is rejected is clear: the work started with `Task.detached` runs independently of the main actor, while `moved` is state of the main actor. The same instance could be touched from two places at once, and this is exactly the definition of a data race. The compiler shows on which line the instance leaks into two isolation regions. One of the solutions is not to move the value, or to put it under isolation: placing the counter inside an actor, as the measurements in this lesson do. Because the compiler catches the problem before the program runs, the error is seen on the day it is written and not on a day when the program runs wrongly.

The **main actor (`@MainActor`)** is a single predefined isolation region. Only code running on the main actor can touch the state of a type marked with `@MainActor`; a call from anywhere else requires `await`. The top-level code of a script runs on the main actor as well. The class below carries this marking and keeps a counter.

```swift
// Screen.swift — a class bound to the main actor
@MainActor
final class Screen {
    private(set) var taps = 0

    func tap() {
        taps += 1
    }
}
```

The measurement starts five tasks in the background; each calls the `tap` method with `await`.

```swift
// main.swift — a class bound to the main actor is reached from other tasks with await
let screen = Screen()

await withTaskGroup(of: Void.self) { group in
    for _ in 1...5 {
        group.addTask { await screen.tap() }
    }
}

print("taps \(screen.taps)")
```

```
taps 5
```

Five calls gave five increments, with no loss. The calls entered the queue of the main actor and were handled one by one. Although `screen` is a class, it could be captured by the tasks: classes bound to the main actor count as transferable, because their state is touched from a single isolation region only.

#### Task Groups

The measurements above used a **task group**. A group starts child tasks whose number can be decided at run time and waits for all of them to finish; with `for await` the results are collected as they finish. The order in which results arrive is undefined, which is why the measurements of this lesson sort them before printing. For a few jobs whose number is known at compile time there is `async let`; each binding is a single child task, and its result is read by awaiting the name of the binding. An `async let` binding starts the expression on its right side as a child task; the result is read with `await`.

#### The Bounding Measurement

The question is: when does `async let` start. The answer that comes to mind is the line where the result is requested, that is, the place where `await` is written. To test this, the result of one binding is read and the second is never read. The actor counts whether both bindings called the `bump` method.

```swift
// Counter.swift — an actor that keeps the number of calls
actor Counter {
    private(set) var calls = 0

    func bump() -> Int {
        calls += 1
        return calls
    }
}
```

```swift
// main.swift — async let starts on the line where it is set up, even if it is not awaited
let counter = Counter()

do {
    async let waited = counter.bump()
    async let ignored = counter.bump()
    _ = await waited
}

print("calls \(await counter.calls)")
```

```
calls 2
```

Two calls were counted. `ignored` was never awaited, but the work still ran before the scope ended: not awaiting the result did not stop the work from running. On scope exit Swift cancels the child task that was not awaited and waits for it to finish; because `bump` does not look at cancellation, it completes its run. This measurement shows a limit. In an ordinary call, the expression is evaluated where the call is written and with the caller waiting; `async let` instead starts a child task without waiting. The two rules belong to different areas: an `async let` is not an expression but a task, and its side effect is independent of whether the result is read. For this reason, evaluation for `async let` does not wait for use.

**MA6.** Actor methods that contain a suspension point were not measured. The measurements were made with a single actor and four or five concurrent tasks; it was not shown that the same rule holds in much larger groups. The order in which the tasks ran was not measured, only the numbers were read. The case where a cancelled task is left half done in a method that looks at cancellation was not measured. The measurement shows only that the work runs even if it is not awaited; whether the work started on the binding line or later cannot be separated by this measurement.

#### Summary

- An actor protects its state inside itself and queues outside access with `await`; the mutable state of an actor cannot be reached without writing `await`.
- A `lazy` property in an actor is evaluated once even when it is read from several concurrent tasks, and it is set up on the first read.
- Moving a value that is not `Sendable` between tasks is rejected at compile time; one of the solutions, the one measured in this lesson, is to put the value under isolation.
- An `async let` binding starts a child task; even if its result is never awaited, the work runs before the scope ends.
- This lesson's moment: **on first use**. The lazy property of an actor is set up once, on the first read, under concurrent reads.

#### Course Wrap-Up

The twenty-four lessons of this course answered a single question: when is an expression evaluated. Each lesson measured one expression and stated its moment with one of four names. In the table, the lesson, the measured expression, the moment and the limit of that lesson sit side by side.

| Lesson | Measured expression | Moment | Limit |
|---|---|---|---|
| Swift's Design Goals | The right side of a `let` constant | `immediately` | If the same expression is bound twice to a single `Probe`, the rule says `on-every-use` |
| Constants and Variables | The initial value of a local constant | `immediately` | A global constant in another file is set up on first access |
| Basic Types | The type conversion on a `let` line | `immediately` | An unread tuple element is evaluated too |
| String Operations | The `description` call in an interpolation | `on-every-use` | A string stored in a `let` is built once |
| Operators | The right side of the `\|\|` operator when the left side is true | `never` | A function that does not take its right side with `@autoclosure` evaluates it before the call |
| Control Flow | The `where` condition after a match | `never` | In a loop the condition is asked on every pass, and `while` asks once more on exit |
| Functions | A default argument expression | `on-every-use` | A supplied argument is evaluated before the call even if the body does not read it |
| Closures | The closure body | `on-every-use` | An expression in the capture list is evaluated once when the closure is set up |
| Optionals | The `map` transformer on an empty box | `never` | In a `.some(nil)` box whose outer layer is filled, the transformer runs |
| Unwrapping Optionals | The right side of `if let` | `immediately` | Everything after the empty link of a chain is skipped, an independent expression on the same line is not |
| Structures and Classes | The copy of a document made on write | `on-first-use` | In a document with a single owner or in a class field, the copy is never made |
| Enumerations | The expression of an associated value | `immediately` | A computed property of the enumeration runs on every read |
| Properties | The initial value of a `lazy` property | `on-first-use` | In a structure each copy sets up its own `lazy` value separately |
| Protocols | The default implementation in a protocol extension | `on-every-use` | The moment is decided not by the protocol but by the type that satisfies the requirement |
| Extensions | A computed property and a method added by an extension | `on-every-use` | A `static let` in an extension is set up once on first access |
| Generics | The `lazy.map` transformer | `on-every-use` | An unread element of a lazy sequence is never transformed |
| Error Handling | The expression after `throw` | `never` | A `defer` block runs on every exit |
| Access Control | A `private lazy` cache | `on-first-use` | The moment is decided not by the access level but by the kind of the property |
| Automatic Reference Counting | The `deinit` body | `on-every-use` | Releasing while a second reference exists does not run `deinit` |
| Strong, Weak and Unowned References | The `deinit` body in a retain cycle | `never` | An `unowned` read of a gone instance cannot be measured, it stops the program |
| Capturing in Closures | An expression in the capture list | `immediately` | A closure that is not stored builds no cycle |
| Property Wrappers | The `wrappedValue` getter | `on-every-use` | A wrapper that takes `@autoclosure` turns the moment into `on-first-use` |
| Result Builders | The expression of an unchosen branch | `never` | Which branch is chosen is decided at run time |
| Concurrency Safety | A `lazy` property in an actor | `on-first-use` | An `async let` whose result is not awaited still runs |

The distribution of the twenty-four lessons is as follows: six are `immediately`, four are `on-first-use`, eight are `on-every-use`, six are `never`. This count comes from the moment column of the table. The distribution of the eight core expressions of the course is 2, 1, 3 and 2. The two are not the same thing: the core counts eight expressions, the table counts twenty-four lessons. The moment of a lesson belongs to the expression that lesson measured.

What the course finishes is teaching how to read an expression together with its rule. The same expression can give each of the four moments depending on how it is written: a local constant is `immediately`, a computed property is `on-every-use`, a `lazy` property is `on-first-use`, an unchosen branch is `never`. The habit the course leaves is, on seeing an expression, to ask which rule it stands under instead of trying to guess its moment from how it is written. This course measured the language itself.

