There is no break in a for loop — deliberately. A break-driven search
forces sequential execution, exactly what Crow's loops exist to avoid. In
its place, three builtins ask the three questions searches actually ask —
and because Crow implements the early exit, they stop across all cores
at once:
1 2 3 4 5 6 7
fn is_big[x]
return x gt 1000
nums = [3, 12, 4021, 55]
log[any[nums, is_big]]
log[all[nums, is_big]]
log[find[nums, is_big]]expected output — from the book, verified by crow test --book
true
false
4021Predicates are named functions — the same functions-as-values idea from chapter 4, and every predicate is independently testable.
find returns the first matching element. And when nothing matches? It
returns the value you already know how to read — an error value:
1 2 3 4 5 6 7 8 9 10
fn is_big[x]
return x gt 1000
fn is_negative[x]
return x lt 0
nums = [3, 12, 4021, 55]
missing = find[nums, is_negative]
log[missing.ok]
log[missing.reason]expected output — from the book, verified by crow test --book
false
no matchNo sentinel -1, no null, no exception — a miss is a value carrying its
own explanation, checked with .ok like every other fallible result.