How do I process items until a condition is met without break?
← Control Flow Without break/continue/return · Ref: Q287
In Java you write: while(true) { item = next(); if (done(item)) break; process(item); }. EK9 replaces this with guard-driven termination: the while loop condition itself controls when to stop.
THE PROBLEM
Processing items until a termination condition is the most common use of while(true) with break. The break is buried inside the loop body, making the termination condition hard to find.
PATTERN 1: WHILE WITH GUARD VARIABLE
Use a Boolean flag that controls the while loop:
done <- Boolean(false) idx <- 0 while ~done? and idx < length items item <- items.getOrDefault(idx, "") if item == "STOP" done: true else process(item) idx: idx + 1
The termination condition is in the while expression, not buried in the body.
PATTERN 2: COUNTING WITH FOR-RANGE
When processing up to a known maximum:
for count in 1 ... maxItems if ~finished? item <- getItem(count) if isTerminal(item) finished: true else process(item)
PATTERN 3: STREAM WITH HEAD
When you want the first N items that satisfy a condition:
results <- cat items | filter by isActive | head 10 | collect as List of String
The pipeline stops after 10 active items. No loop, no break, no counter.
GUARD-DRIVEN VS BREAK-DRIVEN
Break-driven: the loop runs forever, break is the only way out. The termination logic is scattered through the body.
Guard-driven: the while condition states exactly when the loop ends. The body focuses on processing.
See Q66 for while loops. See Q144 for no break. See Q125 for head.
Example
defines module qa.without.processuntil defines function isActive() as pure -> item as String <- active as Boolean: item <> "STOP" and length item > 0 processWithLimit() -> dataItems as List of String readLimit as Integer <- itemsRead as Integer: 0 for pos in 0 ... length dataItems - 1 if itemsRead < readLimit itemsRead: itemsRead + 1 defines program ProcessUntilDemo() stdout <- Stdout() // === PATTERN 1: WHILE WITH GUARD VARIABLE === items <- ["alpha", "bravo", "charlie", "STOP", "delta", "echo"] done <- Boolean(false) idx <- 0 processed <- 0 while ~done and idx < length items item <- items.getOrDefault(idx, "") if item == "STOP" done: true else stdout.println(`Processing: ${item}`) processed: processed + 1 idx: idx + 1 stdout.println(`Processed ${processed} items before STOP`) // === PATTERN 2: COUNTING WITH FOR-RANGE === numbers <- [10, 20, 30, 40, 50, 60, 70] runningTotal <- 0 totalLimit <- 100 exceeded <- Boolean(false) for count in 0 ... length numbers - 1 if ~exceeded currentNum <- numbers.getOrDefault(count, 0) if runningTotal + currentNum > totalLimit exceeded: true else runningTotal: runningTotal + currentNum stdout.println(`Running total (stopped before exceeding 100): ${runningTotal}`) // === PATTERN 3: STREAM WITH HEAD === allItems <- ["", "alpha", "bravo", "", "charlie", "STOP", "delta", "echo", "foxtrot"] activeItems <- cat allItems | filter by isActive | head 3 | collect as List of String stdout.println(`First 3 active items: ${activeItems}`) // === BOUNDED PROCESSING WITH INDEX === dataItems <- ["read1", "read2", "read3", "read4", "read5"] itemsRead <- processWithLimit(dataItems, 3) stdout.println(`Bounded read processed ${itemsRead} items`)
Common mistakes
E01070 — EK9 has no break statement. To stop processing when a condition is met, set a guard flag variable and check it in the while condition. See ek9 -h E01070 for details.
Incorrect:
break
Correct:
done: true
Other ways to ask this
- How do I replace while(true) with break-on-condition in EK9?
- How do I consume items until done without break in EK9?
- How do I write a processing loop that stops on a condition in EK9?
Coming from another language?
Java: while(true) { if (done) break; } or do-while with condition. Python: while True: if done: break. Rust: loop { if done { break; } } or while !done. Go: for { if done { break } }. Kotlin: while(true) { if (done) break }. JavaScript: while(true) { if (done) break; }. EK9: while with guard expression or flag variable, for-range for bounded processing, stream head for take-first-N.
Keywords: alternative, migrate, done, no-return, consume, process, until, guard, null-safe, stop, exhaust, terminate, no-break, loop, safe, isset, while, condition