How do I convert break-based loops from Java or Python to EK9?
← Control Flow Without break/continue/return · Ref: Q288
This shows four common break-based loop patterns and their EK9 equivalents side by side.
SCENARIO 1: FIND FIRST X
Java: for (String s : items) { if (s.length() > 5) { result = s; break; } }
Python: for s in items: if len(s) > 5: result = s; break
EK9 equivalent uses filter + head:
results <- cat items | filter by isLong | head 1 | collect as List of String
The pipeline stops after the first long item. No loop variable, no break.
SCENARIO 2: PROCESS FIRST N MATCHING
Java: int count = 0; for (String s : items) { if (isValid(s)) { process(s); if (++count >= 3) break; } }
EK9 equivalent uses filter + head N:
topN <- cat items | filter by isValid | head 3 | collect as List of String for item in topN process(item)
The stream selects, the loop processes. Each part has one responsibility.
SCENARIO 3: ACCUMULATE UNTIL LIMIT
Java: int sum = 0; for (int n : numbers) { sum += n; if (sum > 100) break; }
EK9 equivalent uses a guard flag:
total <- 0 exceeded <- Boolean(false) for num in numbers if ~exceeded if total + num > 100 exceeded: true else total: total + num
The flag replaces break. The termination condition is checked at loop entry.
SCENARIO 4: SKIP ITEMS THEN TAKE SOME
Java: boolean started = false; int taken = 0; for (String s : items) { if (!started) { if (s.equals("START")) started = true; continue; } process(s); if (++taken >= 2) break; }
EK9 equivalent uses skip + head:
selected <- cat items | skip 2 | head 3 | collect as List of String
For conditional skip, use filter to remove unwanted prefix items.
THE PATTERN
Every break loop decomposes into: what do I want? Express the want as a stream pipeline or a guard-controlled loop.
See Q145 for replacing break and continue. See Q148 for migration rules. See Q275 for AI break patterns.
Example
defines module qa.without.migratebreak defines function isLong() as pure -> item as String <- long as Boolean? minLongLength <- 5 long: length item > minLongLength isValid() as pure -> item as String <- valid as Boolean? minValidLength <- 2 valid: length item > minValidLength formatItem() as pure -> item as String <- formatted as String: `[${item}]` defines program MigrateBreakDemo() stdout <- Stdout() items <- ["hi", "apple", "banana", "fig", "cherry", "date", "elderberry"] // === SCENARIO 1: FIND FIRST LONG ITEM === // Java: for (s : items) { if (s.length() > 5) { result = s; break; } } firstLong <- cat items | filter by isLong | head 1 | collect as List of String stdout.println(`First long item: ${firstLong}`) // === SCENARIO 2: PROCESS FIRST 3 VALID === // Java: count = 0; for (s : items) { if (valid(s)) { process(s); if (++count >= 3) break; } } topThree <- cat items | filter by isValid | head 3 | collect as List of String for item in topThree stdout.println(`Processing valid: ${formatItem(item)}`) // === SCENARIO 3: ACCUMULATE UNTIL LIMIT === // Java: sum = 0; for (n : numbers) { sum += n; if (sum > 100) break; } numbers <- [10, 25, 30, 45, 50, 60] total <- 0 totalLimit <- 100 exceeded <- Boolean(false) for num in numbers if ~exceeded if total + num > totalLimit exceeded: true else total: total + num stdout.println(`Accumulated total (under 100): ${total}`) // === SCENARIO 4: SKIP ITEMS THEN TAKE SOME === // Java: started = false; taken = 0; for (s : items) { if (!started) { continue; } process(s); if (++taken >= 2) break; } selected <- cat items | skip 2 | head 3 | collect as List of String stdout.println(`Skipped 2, took 3: ${selected}`) // === ALL SCENARIOS COMBINED === fruits <- ["fig", "apple", "banana", "cherry", "date", "elderberry", "grape"] longFruits <- cat fruits | filter by isLong | skip 1 | head 2 | collect as List of String stdout.println(`Skip 1 long, take 2: ${longFruits}`)
Common mistakes
E01070 — EK9 has no break statement. When migrating accumulate-until-limit loops from Java or Python, replace break with a Boolean flag checked in the loop condition. See ek9 -h E01070 for details.
Incorrect:
break
Correct:
exceeded: true
Other ways to ask this
- What are before and after examples for converting break loops to EK9?
- How do I migrate a for loop with break to EK9 idioms?
- What are the EK9 equivalents of common break loop patterns?
Coming from another language?
Java: for loop with break on condition, counter + break for first-N, accumulator + break on limit. Python: for with break, enumerate + break, itertools.islice as alternative. Rust: for with break, iter().take(n).filter(), iter().scan() for accumulation. Go: for with break, manual counter. Kotlin: for with break, take() and filter() on sequences. JavaScript: for with break, Array.find(), Array.some(). EK9: filter + head for selection, guard variables for accumulation, skip + head for windowing.
Keywords: stream, after, before, no-break, no-return, convert, loop, alternative, imperative, refactor, side, migration, migrate, break