Beginner

Control Flow in REXX

Master conditionals and loops in REXX - IF/ELSE, SELECT/WHEN, DO loops, and LEAVE/ITERATE with Docker-ready examples using Regina REXX

Control flow is what turns a list of instructions into a program that makes decisions and repeats work. As an imperative, structured language, REXX gives you a clean, English-like set of keywords for branching and looping—IF, SELECT, and DO—without the punctuation overhead found in many other languages.

True to Mike Cowlishaw’s design goals, REXX control flow reads almost like plain English. There are no curly braces, no colons, and no significant indentation. A block of statements is simply wrapped in DO ... END, and conditions use ordinary words like then, else, when, and otherwise. Because REXX is typeless, conditions evaluate strings and numbers interchangeably—1, '1', and the result of 2 - 1 all compare as equal.

In this tutorial you’ll learn how to branch with IF/THEN/ELSE, handle multiple cases with SELECT/WHEN, and iterate using REXX’s remarkably flexible DO loop. You’ll also see how LEAVE and ITERATE give you precise control over loop execution.

Conditionals with IF/THEN/ELSE

The IF instruction tests a condition and runs an instruction when it’s true. An optional ELSE clause handles the false case. When you need more than one statement in a branch, wrap it in DO ... END.

Create a file named control_flow_if.rexx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* Conditionals in REXX */

/* Simple IF / ELSE */
temperature = 75
if temperature > 80 then
    say "It's hot outside"
else
    say "It's pleasant outside"

/* Multiple statements need DO ... END */
age = 20
if age >= 18 then do
    say "You are an adult"
    say "You can vote"
end
else do
    say "You are a minor"
end

/* Chained conditions with ELSE IF */
score = 85
if score >= 90 then
    say "Grade: A"
else if score >= 80 then
    say "Grade: B"
else if score >= 70 then
    say "Grade: C"
else
    say "Grade: F"

A few things to notice:

  • The condition needs no parentheses, though you may add them for clarity.
  • then is required after the condition—it’s part of REXX’s grammar, not optional punctuation.
  • An ELSE clause attaches to a single instruction. Because an entire IF is itself one instruction, else if ... chains naturally without any special elif keyword.
  • Comparison uses a single = (REXX has no ==). Other operators include \= (not equal), <, >, <=, and >=.

Multi-way Branching with SELECT

When you have several mutually exclusive cases, SELECT is clearer than a long IF/ELSE chain. It evaluates each WHEN condition in order and runs the first one that’s true. The OTHERWISE clause is the catch-all.

Create a file named control_flow_select.rexx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* SELECT statements in REXX */

/* Match against string values */
day = "WED"
select
    when day = "SAT" | day = "SUN" then
        say "It's the weekend!"
    when day = "FRI" then
        say "Almost the weekend!"
    when day = "MON" then
        say "Start of the work week"
    otherwise
        say "It's a regular work day"
end

/* Use ranges instead of exact matches */
hour = 14
select
    when hour < 12 then
        say "Good morning"
    when hour < 18 then
        say "Good afternoon"
    otherwise
        say "Good evening"
end

Key points about SELECT:

  • Each WHEN is a full boolean condition, not just a value to match—so you can test ranges, combine conditions with | (or) and & (and), and call functions.
  • The first matching WHEN wins; remaining conditions are not evaluated.
  • OTHERWISE is strongly recommended. If no WHEN matches and there’s no OTHERWISE, REXX raises a syntax error.
  • The whole construct is closed with a single END.

Loops with DO

The DO instruction is REXX’s universal looping construct. It handles counted loops, conditional loops, and simple repetition—all with the same keyword.

Create a file named control_flow_loops.rexx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* Loops in REXX */

/* Counted loop: index from 1 to 5 */
say "Counting up:"
do i = 1 to 5
    say "  i =" i
end

/* Counted loop with a step using BY */
say "Counting by twos:"
do n = 0 to 10 by 2
    say "  n =" n
end

/* Repeat a fixed number of times (no index) */
say "Three cheers:"
do 3
    say "  Hooray!"
end

/* DO WHILE: test the condition before each iteration */
say "Countdown:"
count = 3
do while count > 0
    say "  count =" count
    count = count - 1
end

/* DO UNTIL: test the condition after each iteration */
say "Runs at least once:"
x = 10
do until x >= 10
    say "  x =" x
    x = x + 1
end

This single example shows the main loop forms:

  • do i = 1 to 5 counts an index variable automatically.
  • by 2 changes the step; it can be negative to count down.
  • do 3 repeats a block a fixed number of times without an index.
  • do while checks the condition before the body, so it may run zero times.
  • do until checks after the body, so it always runs at least once.

Loop Control with LEAVE and ITERATE

LEAVE exits a loop immediately (like break in other languages), and ITERATE skips to the next iteration (like continue). Combined with DO FOREVER, they let you build loops that run until an arbitrary condition is met.

Create a file named control_flow_control.rexx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Loop control in REXX */

/* LEAVE exits a loop early */
say "Searching for 7:"
do i = 1 to 100
    if i = 7 then do
        say "  Found 7 at iteration" i
        leave
    end
end

/* ITERATE skips the rest of the current iteration */
say "Odd numbers from 1 to 10:"
do j = 1 to 10
    if j // 2 = 0 then iterate
    say "  Odd:" j
end

/* DO FOREVER loops until a LEAVE is reached */
say "Accumulating until the sum exceeds 20:"
total = 0
k = 1
do forever
    total = total + k
    if total > 20 then leave
    k = k + 1
end
say "  Final total:" total "after adding 1 to" k

Notes on loop control:

  • LEAVE and ITERATE act on the innermost loop by default. You can target an outer loop by naming its index variable, e.g. leave i.
  • // is REXX’s remainder operator, so j // 2 = 0 tests whether j is even.
  • DO FOREVER has no exit condition of its own—you must use LEAVE (or RETURN/EXIT) to break out, or it will run indefinitely.

Running with Docker

The examples run unchanged in the Regina REXX container.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Pull the Regina REXX image
docker pull rzuckerm/rexx:3.6-5.00-1

# Run the conditional example
docker run --rm -v $(pwd):/app -w /app rzuckerm/rexx:3.6-5.00-1 rexx /app/control_flow_if.rexx

# Run the SELECT example
docker run --rm -v $(pwd):/app -w /app rzuckerm/rexx:3.6-5.00-1 rexx /app/control_flow_select.rexx

# Run the loops example
docker run --rm -v $(pwd):/app -w /app rzuckerm/rexx:3.6-5.00-1 rexx /app/control_flow_loops.rexx

# Run the loop-control example
docker run --rm -v $(pwd):/app -w /app rzuckerm/rexx:3.6-5.00-1 rexx /app/control_flow_control.rexx

Expected Output

Running control_flow_if.rexx:

It's pleasant outside
You are an adult
You can vote
Grade: B

Running control_flow_select.rexx:

It's a regular work day
Good afternoon

Running control_flow_loops.rexx:

Counting up:
  i = 1
  i = 2
  i = 3
  i = 4
  i = 5
Counting by twos:
  n = 0
  n = 2
  n = 4
  n = 6
  n = 8
  n = 10
Three cheers:
  Hooray!
  Hooray!
  Hooray!
Countdown:
  count = 3
  count = 2
  count = 1
Runs at least once:
  x = 10

Running control_flow_control.rexx:

Searching for 7:
  Found 7 at iteration 7
Odd numbers from 1 to 10:
  Odd: 1
  Odd: 3
  Odd: 5
  Odd: 7
  Odd: 9
Accumulating until the sum exceeds 20:
  Final total: 21 after adding 1 to 6

Key Concepts

  • IF/THEN/ELSE branches on a condition. then is mandatory, and multiple statements in a branch must be grouped with DO ... END.
  • Chained ELSE IF works naturally because an IF is a single instruction—REXX needs no dedicated elif/elseif keyword.
  • SELECT/WHEN/OTHERWISE handles multi-way branching cleanly. Each WHEN is a full condition, and OTHERWISE should always be present to avoid a runtime error when nothing matches.
  • The DO loop is universal: DO i = 1 TO n [BY step] for counted loops, DO n for fixed repetition, DO WHILE for pre-tested loops, DO UNTIL for post-tested (run-at-least-once) loops, and DO FOREVER for open-ended loops.
  • LEAVE and ITERATE provide break/continue behavior and can target a named outer loop (e.g. leave i).
  • No ternary operator: REXX has no ?: conditional expression—use a short IF/THEN/ELSE or a SELECT instead.
  • Typeless comparisons: conditions compare strings and numbers transparently, and a single = is the equality operator (there is no ==).
  • Operators in conditions: combine tests with & (and), | (or), and \ (not); use // for remainder when writing numeric tests.

Running Today

All examples can be run using Docker:

docker pull rzuckerm/rexx:3.6-5.00-1
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining