How do I find the first match and stop searching without break?
← Control Flow Without break/continue/return · Ref: Q284
For simple first-match, use filter + head 1 in a stream pipeline. For complex search with transformation or context, use a function with unset return and a for loop.
SIMPLE FIRST MATCH: FILTER + HEAD
The basic pattern for finding the first match:
first <- cat items | filter by predicate | head 1 | collect as List of String
This stops processing after the first match. No break needed.
PATTERN 1: SEARCH WITH TRANSFORMATION
Find the first match and return a TRANSFORMED result, not the match itself:
findAndTransform()
-> items as List of String
<- result as String: String()
for item in items
if length item > 5 and ~result?
result :=? item + " (long)"
The :=? ensures only the first long item gets transformed and assigned.
PATTERN 2: SEARCH WITH INDEX
Find an item AND its position:
findWithIndex()
-> items as List of String, target as String
<- position as Integer: Integer()
idx <- 0
for item in items
if item == target and ~position?
position :=? idx
idx: idx + 1
The caller gets the index of the first occurrence, or an unset Integer if not found.
PATTERN 3: MULTI-FIELD SEARCH
Search objects by multiple criteria using a helper predicate:
isMatch() as pure -> item as String <- matched as Boolean: item contains "admin" and length item > 7 found <- cat users | filter by isMatch | head 1 | collect as List of String
KEY INSIGHT
Stream filter + head for simple cases. Function decomposition with :=? for complex ones where you need transformation, context, or multi-step logic.
See Q145 for basic filter + head. See Q125 for head, tail, and skip. See Q89 for stream pipelines. See Q50 for unset return as signal.
Example
defines module qa.without.findmatch defines function isLong() as pure -> item as String <- long as Boolean? minLongLength <- 5 long: length item > minLongLength findAndTransform() -> items as List of String <- result as String: String() minLongLength <- 5 for item in items if length item > minLongLength and ~result? result :=? item + " (long)" findWithIndex() -> items as List of String target as String <- position as Integer: Integer() idx <- 0 for item in items if item == target and ~position? position :=? idx idx: idx + 1 containsAdmin() as pure -> item as String <- matched as Boolean? minAdminLength <- 7 matched: item contains "admin" and length item > minAdminLength defines program FindFirstDemo() stdout <- Stdout() items <- ["hi", "apple", "banana", "cherry", "date", "elderberry"] // === SIMPLE: FILTER + HEAD === firstLong <- cat items | filter by isLong | head 1 | collect as List of String stdout.println(`First long item: ${firstLong}`) // === SEARCH WITH TRANSFORMATION === transformed <- findAndTransform(items) if transformed? stdout.println(`Transformed: ${transformed}`) // === SEARCH WITH INDEX === pos <- findWithIndex(items, "cherry") if pos? stdout.println(`Cherry found at index: ${pos}`) notFoundPos <- findWithIndex(items, "mango") if ~notFoundPos? stdout.println("Mango not found in list") // === MULTI-FIELD SEARCH === users <- ["user_joe", "admin_alice", "user_bob", "admin_charlie"] admins <- cat users | filter by containsAdmin | head 1 | collect as List of String stdout.println(`First admin: ${admins}`)
Common mistakes
E01070 — EK9 has no break statement. To find the first match, use guard assignment (:=?) which only assigns when the variable is unset, replacing break-on-found. See ek9 -h E01070 for details.
Incorrect:
break
Correct:
position :=? idx
Other ways to ask this
- How do I do early termination search without break in EK9?
- How do I return the first matching item from a list in EK9?
- How do I search with transformation without break in EK9?
Coming from another language?
Java: for (item : list) { if (match) { result = item; break; } } or stream().filter().findFirst(). Python: for item in list: if match: result = item; break, or next(x for x in list if match, None). Rust: iter().find(|x| predicate). Go: for _, item := range list { if match { return item } }. Kotlin: list.firstOrNull { predicate }. EK9: cat items | filter by predicate | head 1 | collect, or function with :=? for complex search.
Keywords: termination, linear, match, search, transform, alternative, first, index, no-break, filter, find, lookup, no-return, head, stop, early