# L05: Scope, State, and Iteration

## Predict Before You Run

Trace this loop before writing the helper:

```ts
const items = ["coin", "trap", "coin"];
const target = "coin";
let count = 0;

for (const item of items) {
  if (item === target) {
    count += 1;
  }
}
```

Fill this trace table before running or editing code:

| Step | item | count before | count after |
| --- | --- | --- | --- |
| 1 | "coin" | 0 | ___ |
| 2 | "trap" | ___ | ___ |
| 3 | "coin" | ___ | ___ |

Prediction questions:

1. Which value changes each loop?
2. Which value stays the same?
3. What should the final count be?
4. What should happen for an empty list?

## Scope Check

Predict which names exist after the block:

```ts
let status = "waiting";

if (status === "waiting") {
  const nextStatus = "playing";
  status = nextStatus;
}

// Which names can you use here: status, nextStatus, or both?
```

## Programming Challenge: Complete The Helper

Download [the L05 count-matches starter](/materials/labs/snippets/L05-count-matches-starter.ts.txt), copy it into a scratch file, or solve the same skeleton on paper. Add only the missing lines:

```ts
export function countMatches(items: string[], target: string): number {
  let count = 0;

  for (const item of items) {
    // TODO: when should count change?
  }

  return count;
}
```

Expected results:

```ts
countMatches(["coin", "trap", "coin"], "coin") === 2;
countMatches(["trap"], "coin") === 0;
countMatches([], "coin") === 0;
```

Stop when you can explain the accumulator update in one sentence.


## Common Bugs

- Changing browser UI files before the rule helper is testable.
- Adding state changes inside a function that should be a pure helper.
- Trusting generated code without a small test for the boundary case.

## Bonus Puzzles

- Add a reset rule.
- Trace the loop with an empty list.
- Ask AI to produce a buggy loop and fix it.
