Control Flow
IF / ELSE IF / ELSE, IF SOME, SWITCH, WHILE, WHILE SOME, FOREACH. All blocks use OPEN NEST / CLOSE NEST.
IF / ELSE IF / ELSE
CALCULATE "85" SET ?score
IF ?score IS GREATER THAN 90
OPEN NEST EMIT "A" CLOSE NEST
ELSE IF ?score IS GREATER THAN 70
OPEN NEST EMIT "B" CLOSE NEST
ELSE IF ?score IS GREATER THAN 50
OPEN NEST EMIT "C" CLOSE NEST
ELSE
OPEN NEST EMIT "F" CLOSE NEST
Try it ›
(* IF with null check *)
FETCH "https://httpbin.org/uuid" SET ?resp
AFTER IF ?resp(uuid) IS NOT NULL
OPEN NEST EMIT "got UUID: " & ?resp(uuid) CLOSE NEST
ELSE OPEN NEST EMIT "no UUID returned" CLOSE NEST
Try it ›
(* IF with string contains *)
STRING "Engineering Magic" SET ?s
AFTER IF ?s CONTAINS "Magic"
OPEN NEST EMIT "found it" CLOSE NEST
ELSE OPEN NEST EMIT "not found" CLOSE NEST
Try it ›
(* IF with regex MATCHES *)
STRING "user@example.com" SET ?email
AFTER IF ?email MATCHES "^[^@]+@[^@]+\.[^@]+$"
OPEN NEST EMIT "valid email" CLOSE NEST
ELSE OPEN NEST EMIT "invalid email" CLOSE NEST
Try it ›
Comparison operators
| Operator | Meaning | Context |
|---|---|---|
IS EQUAL TO | Equality with type coercion | IF |
IS IDENTICAL TO | Strict equality — type and value | IF |
IS NOT EQUAL TO | Inequality with type coercion | IF |
IS GREATER THAN | Numeric greater than | IF |
IS LESS THAN | Numeric less than | IF |
IS GREATER THAN OR EQUAL TO | Numeric ≥ | IF |
IS LESS THAN OR EQUAL TO | Numeric ≤ | IF |
IS NULL | Value is null | IF |
IS NOT NULL | Value is not null | IF |
CONTAINS / CONTAIN | String or array contains substring/element | IF |
MATCHES / MATCH | Regex match — returns boolean | IF |
ARE EQUAL TO | Any element equals value | IF SOME / WHILE SOME |
ARE IDENTICAL TO | Any element strictly equals value | IF SOME / WHILE SOME |
ARE NOT EQUAL TO | Any element does not equal value | IF SOME / WHILE SOME |
ARE GREATER THAN | Any element is greater than value | IF SOME / WHILE SOME |
ARE LESS THAN | Any element is less than value | IF SOME / WHILE SOME |
ARE GREATER THAN OR EQUAL TO | Any element ≥ value | IF SOME / WHILE SOME |
ARE LESS THAN OR EQUAL TO | Any element ≤ value | IF SOME / WHILE SOME |
ARE NULL | Any element is null | IF SOME / WHILE SOME |
ARE NOT NULL | Any element is not null | IF SOME / WHILE SOME |
IF SOME — any-match on arrays
Branches if any element of the array matches. OR is the fallback when no element matches.
SPLIT "active,inactive,active" WITH "," SET ?s
AFTER IF SOME ?s ARE EQUAL TO "active"
OPEN NEST EMIT "at least one active" CLOSE NEST
ELSE OPEN NEST EMIT "none active" CLOSE NEST
Try it ›
(* Check if any score is above threshold *)
SPLIT "45,82,91,33,67" WITH "," SET ?scores
AFTER IF SOME ?scores ARE GREATER THAN "80"
OPEN NEST EMIT "at least one high scorer" CLOSE NEST
ELSE OPEN NEST EMIT "no high scorers" CLOSE NEST
Try it ›
(* Check if any value is null *)
NEW ARRAY OPEN NEST ENLIST "ok" ENLIST null ENLIST "fine" CLOSE NEST SET ?vals
AFTER IF SOME ?vals ARE NULL
OPEN NEST EMIT "nulls present" CLOSE NEST
ELSE OPEN NEST EMIT "all values set" CLOSE NEST
SWITCH / CASE / DEFAULT
Match a value against multiple literal cases. DEFAULT is the fallback.
STRING "pro" SET ?tier
SWITCH ?tier
CASE "free"
OPEN NEST EMIT "100 queries/day" CLOSE NEST
CASE "starter"
OPEN NEST EMIT "10,000 queries/day" CLOSE NEST
CASE "pro"
OPEN NEST EMIT "100,000 queries/day" CLOSE NEST
CASE "enterprise"
OPEN NEST EMIT "1,000,000 queries/day" CLOSE NEST
DEFAULT
OPEN NEST EMIT "unknown tier" CLOSE NEST
Try it ›
WHILE
CALCULATE "1" SET ?i
WHILE ?i IS LESS THAN OR EQUAL TO 5
OPEN NEST
EMIT ?i
AFTER CALCULATE "?i + 1" SET ?i
CLOSE NEST
Try it ›
WHILE SOME
Loops while any element of the array matches the condition. Re-evaluate the array each iteration by reassigning it.
SPLIT "pending,pending,done" WITH "," SET ?states
WHILE SOME ?states ARE EQUAL TO "pending"
OPEN NEST
EMIT "still pending..."
AFTER SLEEP "1s"
AFTER FETCH "https://api.example.com/status" SET ?resp
AFTER SPLIT ?resp(states) WITH "," SET ?states
CLOSE NEST
AFTER EMIT "all done"
FOREACH
Iterates an array. Inside the block: !INDEX is the 0-based position, !VALUE is the current item (same as the alias variable). Each iteration's result is collected — add SET ?results after CLOSE NEST to capture all results as an array.
SPLIT "red,green,blue" WITH "," SET ?colors
AFTER FOREACH ?colors AS ?color
OPEN NEST
EMIT ?color & " (#" & !INDEX & ")"
CLOSE NEST
Try it ›
(* Capture all results — SET after CLOSE NEST collects every iteration value *)
SPLIT "hello,world,oql" WITH "," SET ?words
AFTER FOREACH ?words AS ?w
OPEN NEST
UPPER ?w SET ?up
AFTER EMIT ?up
CLOSE NEST
SET ?uppers
AFTER EMIT ?uppers
(* → ["HELLO","WORLD","OQL"] *)
Try it ›
(* FOREACH over query results *)
QUERY "products" FROM "shop" SET ?rows
AFTER FOREACH ?rows AS ?p
OPEN NEST
EMIT ?p(name) & " — R" & ?p(price)
CLOSE NEST
(* Nested FOREACH *)
SPLIT "a,b" WITH "," SET ?outer
AFTER FOREACH ?outer AS ?x
OPEN NEST
SPLIT "1,2,3" WITH "," SET ?inner
AFTER FOREACH ?inner AS ?n
OPEN NEST
EMIT ?x & ?n
CLOSE NEST
CLOSE NEST
Try it ›
Inside FOREACH:
?alias and !VALUE both hold the current item. !INDEX is the 0-based position. FOREACH on a non-array value wraps it in a single-element array and iterates once.