Control flow and pattern matching
Conditionals, loops, and match, all in prefix form.
Like every NURL expression, control flow uses prefix form: the keyword comes first, then its operands.
Conditionals: ?
? cond then elseBoth then and else are full expressions. A block { ... } is the usual
form. Both branches must give the same type.
? > x 0 { ( puts `positive\n` ) } { ( puts `non-positive\n` ) }Chained conditionals read top to bottom. Each else slot holds the next
?:
? div3
{ ( nurl_print `Fizz\n` ) }
? div5
{ ( nurl_print `Buzz\n` ) }
{ ( nurl_println_int i ) }Count the operands
? takes exactly three operands. It is easy to get a chain of & a b c d
inside a condition wrong. See Binary operators below.
Loops
While
~ cond { body }: ~ i i 1
~ <= i 10 {
( nurl_println_int i )
= i + i 1
}Foreach
~ item collection { body }collection must be a slice. The element binding is a borrow. It is not
owned, the runtime does not drop it at the end of the iteration, and you
cannot reassign it.
: [i nums [i | 1 2 3 4 5]
~ n nums {
( puts ( nurl_str_int n ) )
}A foreach can walk a struct's field directly (grammar v2.10):
~ x . bag items { ( puts ( nurl_str_int x ) ) }The loop body may not mutate collection itself. The borrow checker rejects
push, remove, clear, and similar calls on it — by path, so a loop over
. s a may still change . s b. See
Memory and ownership.
Break and continue
break exits the innermost ~ loop immediately. continue jumps to the next iteration (advancing the index in a foreach loop). Both run scope-exit drops and ; defers for bindings created inside the loop body up to that point:
~ n nums {
? < n 0 { continue } {}
? == n 99 { break } {}
( nurl_println_int n )
}Defer: ;
; { cleanup_body }; schedules a block to run when the enclosing lexical scope exits — whether by reaching the closing }, returning via ^, propagating an error via \, or exiting a loop with break / continue. Multiple ; statements in the same scope run in reverse (LIFO) order, and only defers whose ; statement was actually reached at runtime execute.
@ process_item → !i s {
( acquire_trace_span )
; { ( release_trace_span ) }
: i v \ ( step_that_may_fail )
^ @ !i s { T v }
}Binary operators
Arithmetic, comparison, shift, and logical operators are all strictly binary — they take exactly two operands. For a chain of more than two, write one operator per pair, n−1 operators for n values:
& a & b c // a && b && c
| | a b c d // a || b || c || dThe compiler rejects the common mistake of writing a flat n-ary chain inside ? (where extra values would otherwise become the ?'s then/else operands) as a compile error by default (demoted to a warning only with --no-strict-arity).
Match: ??
?? expr { arm* }Matches an enum value, an ?T option, or a !T E result. You must cover
every variant. Use an explicit arm or a _ wildcard. The compiler
checks this at compile time.
?? val {
JNull → `null`
JNum n → ( nurl_str_int n )
KeyPress c m → ( key_event c m ) // binds two payload values
Ok 200 → `ok` // matches only when payload == 200
_ → `other`
}A pattern can be a variant name, _ for wildcard, or A | B (an or-pattern
that covers several variants with no payload binding). A payload slot can be
an identifier that binds the value, or an integer literal that must match
exactly.
An arm may add a guard — ? condition between the payload and →. The
runtime checks the guard after it binds the payload. A guarded arm does not
by itself satisfy exhaustiveness for its variant. You still need a plain arm
or _ to cover the case where the guard is false.
?? msg {
Move n ? > n 0 → `forward`
Move n → `back-or-stay`
_ → `other`
}?T and !T E are ordinary enums, so they match the
same way. Use T / F as the tag pattern for ?T:
?? maybe_n {
T n → ( nurl_println_int n )
F → ( nurl_print `nothing\n` )
}See Error handling for the full picture, including
the \ try-propagate shortcut.
Channel select
A ?? immediately followed by { (no scrutinee expression) starts a
different construct — a Go-style channel select. It runs the body of
whichever channel becomes ready first. See
Concurrency.
Next
Last updated on