<!-- canonical: efficientnewlanguage.org/ai/examples/426-the-guard-clause-skipped-the-accounting | ai_layer_version: 0.1.0 | updated: 2026-08-17 -->

# Example 426 — The guard clause skipped the accounting

`the_guard_clause_skipped_the_accounting.eml` - A guard clause was added at the top of a loop. It skipped more than the record it was aimed at.

## EML

```eml
# Self-authored for the EML case corpus (no external origin). A guard clause was
# added at the top of a loop. It skipped more than the record it was aimed at.
#
# The guard is good practice: it takes the invalid case out of the way in one
# line and leaves the body un-nested, which is easier to read than wrapping
# everything below it in an `if`. Nothing about it is wrong.
#
# What it changes is which lines of the body run. `continue` does not skip the
# record - it skips every line beneath it, and the accounting was beneath it,
# because the accounting is written last and appended at the bottom.
#
# Both counts are computed by running the same records through both shapes.

# [id, amount, valid]
[["r1", 40, 1], ["r2", 15, 0], ["r3", 30, 1], ["r4", 25, 0], ["r5", 60, 1], ["r6", 10, 0], ["r7", 20, 1]] => records

len(records) => n
"records : " + str(n) ^0
0 => valid_records
for r in records:
    if r[2] == 1:
        valid_records + 1 => valid_records
"  valid   : " + str(valid_records) ^0
"  invalid : " + str(n - valid_records) ^0
"" ^0

# ---- the loop as it was written, with the guard on top ----

0 => seen
0 => counted
0 => total
for r in records:
    seen + 1 => seen
    if r[2] == 0:
        continue
    total + r[1] => total
    counted + 1 => counted

"the loop with the guard at the top" ^0
"  records the loop saw     : " + str(seen) ^0
"  records the loop counted : " + str(counted) ^0
"  total                    : " + str(total) ^0
if seen > counted:
    "  the difference is " + str(seen - counted) + ", which is how many times continue ran" ^0
"" ^0

# ---- what the accounting was supposed to say ----
#
# The counter at the bottom was written to answer "how many records did this
# run process", which includes the ones it declined. That question now has no
# answer in the loop, because the line that answered it is below the guard.

0 => processed
0 => declined
for r in records:
    processed + 1 => processed
    if r[2] == 0:
        declined + 1 => declined
        continue
    0 => ignore

"what the run actually handled" ^0
"  records processed : " + str(processed) ^0
"  of those declined : " + str(declined) ^0
"  of those totalled : " + str(processed - declined) ^0
if processed == n:
    "  every record is accounted for, because the counting happens above the guard" ^0
"" ^0

# ---- the same guard written as an if/else ----
#
# The nested shape keeps the accounting reachable without moving any line. It
# costs one level of indentation and answers both questions.

0 => e_total
0 => e_counted
0 => e_seen
for r in records:
    e_seen + 1 => e_seen
    if r[2] == 1:
        e_total + r[1] => e_total
        e_counted + 1 => e_counted
    else:
        0 => ignore

"the same filter written as if/else" ^0
"  seen : " + str(e_seen) + ", counted : " + str(e_counted) + ", total : " + str(e_total) ^0
if e_total == total:
    if e_counted == counted:
        "  identical answers to the guard version, and seen is still " + str(e_seen) ^0
"" ^0

# ---- where it gets expensive: an accumulator below the guard ----
#
# A running maximum kept at the bottom of the body sees only the records that
# reached the bottom. When the guard skips the largest one, the maximum is not
# merely late - it is wrong, and nothing in the output says so.

0 => max_all
for r in records:
    if r[1] > max_all:
        r[1] => max_all

0 => max_below
for r in records:
    if r[2] == 0:
        continue
    if r[1] > max_below:
        r[1] => max_below

"a running maximum over every record" ^0
"  computed above the guard : " + str(max_all) ^0
"  computed below the guard : " + str(max_below) ^0
if max_all == max_below:
    "  the two agree on this input, because the largest record happens to be valid" ^0
else:
    "  the two disagree by " + str(abs(max_all - max_below)) ^0
"" ^0

# The same two maxima over records where the largest one is invalid.

[["s1", 40, 1], ["s2", 95, 0], ["s3", 30, 1]] => skewed
0 => s_all
for r in skewed:
    if r[1] > s_all:
        r[1] => s_all
0 => s_below
for r in skewed:
    if r[2] == 0:
        continue
    if r[1] > s_below:
        r[1] => s_below
"  the same two maxima where the largest record is invalid" ^0
"  above the guard : " + str(s_all) + ", below the guard : " + str(s_below) ^0
if not (s_all == s_below):
    "  here the placement of one line changes the answer by " + str(s_all - s_below) ^0
"" ^0

# ---- the control: a guard with nothing below it ----
#
# `continue` is not the defect. A guard that is the last decision in the body
# skips nothing, because there is nothing left to skip.

0 => c_seen
0 => c_total
for r in records:
    c_seen + 1 => c_seen
    if r[2] == 1:
        c_total + r[1] => c_total
    if r[2] == 0:
        continue
"control - a guard at the bottom of the body" ^0
"  seen : " + str(c_seen) + ", total : " + str(c_total) ^0
if c_seen == n:
    if c_total == total:
        "  both answers intact, with the same continue in the same loop" ^0
"" ^0

"The guard is correct and the body is easier to read for having it. What it" ^0
"skips is decided by what is written below it, and the accounting is written" ^0
"below everything because it was added last." ^0
```

## Python (deterministic transpilation)

```python
records = [["r1", 40, 1], ["r2", 15, 0], ["r3", 30, 1], ["r4", 25, 0], ["r5", 60, 1], ["r6", 10, 0], ["r7", 20, 1]]
n = len(records)
print("records : " + str(n))
valid_records = 0
for r in records:
    if r[2] == 1:
        valid_records = valid_records + 1
print("  valid   : " + str(valid_records))
print("  invalid : " + str(n - valid_records))
print("")
seen = 0
counted = 0
total = 0
for r in records:
    seen = seen + 1
    if r[2] == 0:
        continue
    total = total + r[1]
    counted = counted + 1
print("the loop with the guard at the top")
print("  records the loop saw     : " + str(seen))
print("  records the loop counted : " + str(counted))
print("  total                    : " + str(total))
if seen > counted:
    print("  the difference is " + str(seen - counted) + ", which is how many times continue ran")
print("")
processed = 0
declined = 0
for r in records:
    processed = processed + 1
    if r[2] == 0:
        declined = declined + 1
        continue
    ignore = 0
print("what the run actually handled")
print("  records processed : " + str(processed))
print("  of those declined : " + str(declined))
print("  of those totalled : " + str(processed - declined))
if processed == n:
    print("  every record is accounted for, because the counting happens above the guard")
print("")
e_total = 0
e_counted = 0
e_seen = 0
for r in records:
    e_seen = e_seen + 1
    if r[2] == 1:
        e_total = e_total + r[1]
        e_counted = e_counted + 1
    else:
        ignore = 0
print("the same filter written as if/else")
print("  seen : " + str(e_seen) + ", counted : " + str(e_counted) + ", total : " + str(e_total))
if e_total == total:
    if e_counted == counted:
        print("  identical answers to the guard version, and seen is still " + str(e_seen))
print("")
max_all = 0
for r in records:
    if r[1] > max_all:
        max_all = r[1]
max_below = 0
for r in records:
    if r[2] == 0:
        continue
    if r[1] > max_below:
        max_below = r[1]
print("a running maximum over every record")
print("  computed above the guard : " + str(max_all))
print("  computed below the guard : " + str(max_below))
if max_all == max_below:
    print("  the two agree on this input, because the largest record happens to be valid")
else:
    print("  the two disagree by " + str(abs(max_all - max_below)))
print("")
skewed = [["s1", 40, 1], ["s2", 95, 0], ["s3", 30, 1]]
s_all = 0
for r in skewed:
    if r[1] > s_all:
        s_all = r[1]
s_below = 0
for r in skewed:
    if r[2] == 0:
        continue
    if r[1] > s_below:
        s_below = r[1]
print("  the same two maxima where the largest record is invalid")
print("  above the guard : " + str(s_all) + ", below the guard : " + str(s_below))
if not s_all == s_below:
    print("  here the placement of one line changes the answer by " + str(s_all - s_below))
print("")
c_seen = 0
c_total = 0
for r in records:
    c_seen = c_seen + 1
    if r[2] == 1:
        c_total = c_total + r[1]
    if r[2] == 0:
        continue
print("control - a guard at the bottom of the body")
print("  seen : " + str(c_seen) + ", total : " + str(c_total))
if c_seen == n:
    if c_total == total:
        print("  both answers intact, with the same continue in the same loop")
print("")
print("The guard is correct and the body is easier to read for having it. What it")
print("skips is decided by what is written below it, and the accounting is written")
print("below everything because it was added last.")
```

## stdout (executed)

```text
records : 7
  valid   : 4
  invalid : 3

the loop with the guard at the top
  records the loop saw     : 7
  records the loop counted : 4
  total                    : 150
  the difference is 3, which is how many times continue ran

what the run actually handled
  records processed : 7
  of those declined : 3
  of those totalled : 4
  every record is accounted for, because the counting happens above the guard

the same filter written as if/else
  seen : 7, counted : 4, total : 150
  identical answers to the guard version, and seen is still 7

a running maximum over every record
  computed above the guard : 60
  computed below the guard : 60
  the two agree on this input, because the largest record happens to be valid

  the same two maxima where the largest record is invalid
  above the guard : 95, below the guard : 40
  here the placement of one line changes the answer by 55

control - a guard at the bottom of the body
  seen : 7, total : 150
  both answers intact, with the same continue in the same loop

The guard is correct and the body is easier to read for having it. What it
skips is decided by what is written below it, and the accounting is written
below everything because it was added last.
```

## Round-trip

`ok: true` — round-trip fixpoint reached (python1 == python2)

## Trace event types

eml:run:start · eml:assign · eml:output · eml:run:done
