Loop while a connection value remains set, processing each iteration.
← Control Flow · Ref: Q1150
Fetch the first value before the loop, test it in the while condition, and fetch the next one at the end of the body:
current <- source.getConnection() while current? stdout.println(current) current: source.getConnection()
The loop ends cleanly when getConnection() returns an unset value.
A while GUARD does not do this. In 'while conn <- supplier.getConnection() with counter < maxIters' the guard runs ONCE, before the loop: it takes one connection (and skips the loop entirely if that is unset), and only the 'with' condition is re-checked on each iteration. So conn stays the first connection for every pass. Use a guard to set up the loop, not to poll. See Q77 for while guard details. See Q971 for declaration guards.
Example
defines module qa.controlflow.whileguard defines class ConnectionSupplier remaining <- 0 ConnectionSupplier() -> count as Integer this.remaining: count getConnection() <- rtn as String: String() if remaining > 0 rtn: `Connection-${remaining}` remaining: remaining - 1 override operator ? as pure <- rtn as Boolean: remaining? defines program WhileGuardDemo() stdout <- Stdout() source <- ConnectionSupplier(4) processed <- 0 // Loop while getConnection() returns a SET value: fetch first, re-fetch at the end of the body current <- source.getConnection() while current? stdout.println(current) processed: processed + 1 current: source.getConnection() stdout.println(`Processed ${processed} connections`) // A while GUARD runs ONCE, before the loop: conn is the first connection on every pass, // and only the 'with' condition is re-checked supplier <- ConnectionSupplier(2) counter <- 0 maxIters <- 3 while conn <- supplier.getConnection() with counter < maxIters stdout.println(`Guarded: ${conn}`) counter: counter + 1
Common mistakes
E07390 — Using a constant Boolean literal (true) as the while-guard's 'with' condition is a pointless expression; supply a real terminating condition instead. See ek9 -h E07390 for details.
Incorrect:
while conn <- supplier.getConnection() with true
Correct:
while conn <- supplier.getConnection() with counter < maxIters
E01073 — 'null' does not exist in EK9; use tri-state semantics (unset/set) with the '?' operator and guards instead. See ek9 -h E01073 for details.
Incorrect:
counter <> null
Correct:
counter < maxIters
Other ways to ask this
- Write code to use a while guard that loops while a value is set
- I have a supplier that eventually returns unset and need to loop until that happens
- Given a function that returns set values for N calls then unset, process each value
- In Java I'd use while ((val = getNext()) != null). Write the EK9 guard equivalent
- Does a while guard call its function again on every iteration?
Coming from another language?
Java: while ((val = getNext()) != null) { process(val); }. Go: for val := getNext(); val != nil; val = getNext(). Rust: while let Some(v) = get_next(). EK9: val <- getNext(), then while val? with val: getNext() at the end of the body. A while guard (while val <- getNext() with cond) runs once, before the loop, so it does not poll.
Keywords: poll, while, loop, guard, isset, unset, declaration, connection