There are two types of looping instructions, repetitive loops and conditional loops. Repetitive loops let you repeat instructions a certain number of times. Conditional loops use a condition to control repeating. All loops, regardless of the type, begin with the DO keyword and end with the END keyword.
The simplest loop tells the language processor to repeat a group of instructions a specific number of times. It uses a constant after the keyword DO.
DO 5
SAY 'Hello!'
END
When you run this example, it produces five lines of Hello!:
Hello!
Hello!
Hello!
Hello!
Hello!
You can also use a variable in place of a constant, as in the following example, which gives you the same results.
number = 5
DO number
SAY 'Hello!'
END
A variable that controls the number of times a loop repeats is called a control variable. Unless you specify otherwise, the control variable increases by 1 each time the loop repeats.
DO number = 1 TO 5
SAY 'Loop' number
SAY 'Hello!'
END
SAY 'Dropped out of the loop when number reached' number
This example results in five lines of Hello! preceded by the number of the loop. The number increases at the bottom of the loop and is tested at the top.
Loop 1
Hello!
Loop 2
Hello!
Loop 3
Hello!
Loop 4
Hello!
Loop 5
Hello!
Dropped out of the loop when number reached 6
You can change the increment of the control variable with the keyword BY as follows:
DO number = 1 TO 10 BY 2
SAY 'Loop' number
SAY 'Hello!'
END
SAY 'Dropped out of the loop when number reached' number
This example has results similar to the previous example except the loops are numbered in increments of two.
Loop 1
Hello!
Loop 3
Hello!
Loop 5
Hello!
Loop 7
Hello!
Loop 9
Hello!
Dropped out of the loop when number reached 11
What happens when the control variable of a loop cannot attain the last number? For example, in the following program segment, count does not increase beyond 1.
DO count = 1 to 10
SAY 'Number' count
count = count - 1
END
The result is called an infinite loop because count alternates between 1 and 0, producing an endless number of lines saying Number 1.
If your program is in an infinite loop, contact the operator to cancel it. An authorized user can issue the CEMT SET TASK PURGE command to halt an exec.
Sometimes you might want to write an infinite loop purposely; for instance, in a program that reads records from a file until it reaches the end of the file. You can use the EXIT instruction to end an infinite loop when a condition is met, as in the following example. More about the EXIT instruction appears in section EXIT Instruction.
/******************************* REXX ********************************/
/* This program processes strings until the value of a string is */
/* a null string. */
/*********************************************************************/
DO FOREVER
PULL string /* Gets string from input stream */
IF string = '' THEN
PULL file_name
IF file_name = '' THEN
EXIT
ELSE
DO
result = process(string) /* Calls a user-written function */
/* to do processing on string. */
IF result = 0 THEN SAY "Processing complete for string:" string
ELSE SAY "Processing failed for string:" string
END
END
This example sends strings to a user-written function for processing and then issues a message that the processing completed successfully or failed. When the input string is a blank, the loop ends and so does the program. You can also end the loop without ending the program by using the LEAVE instruction. The following topic describes this.
The LEAVE instruction causes an immediate exit from a repetitive loop. Control goes to the instruction following the END keyword of the loop. An example of using the LEAVE instruction follows:
/******************************** REXX *******************************/
/* This program uses the LEAVE instruction to exit from a DO */
/* FOREVER loop. */
/*********************************************************************/
DO FOREVER
PULL string /* Gets string from input stream */
IF string = 'QUIT' then
LEAVE
ELSE
DO
result = process(string) /* Calls a user-written function */
/* to do processing on string. */
IF result = 0 THEN SAY "Processing complete for string:" string
ELSE SAY "Processing failed for string:" string
END
END
SAY 'Program run complete.'
The ITERATE instruction stops execution from within the loop and passes control to the DO instruction at the top of the loop. Depending on the type of DO instruction, the language processor increases and tests a control variable or tests a condition to determine whether to repeat the loop. Like LEAVE, ITERATE is used within the loop.
DO count = 1 TO 10
IF count = 8
THEN
ITERATE
ELSE
SAY 'Number' count
END
This example results in a list of numbers from 1 to 10 with the exception of number 8.
Number 1
Number 2
Number 3
Number 4
Number 5
Number 6
Number 7
Number 9
Number 10
DO digit = 1 TO 3
SAY digit
END
SAY 'Digit is now' digit
DO count = 10 BY -2 TO 6
SAY count
END
SAY 'Count is now' count
DO index = 10 TO 8
SAY 'Hup! Hup! Hup!'
END
SAY 'Index is now' index
PARSE PULL file_name
ANSWERS
There are two types of conditional loops, DO WHILE and DO UNTIL. One or more expressions control both types of loops. However, DO WHILE loops test the expression before the loop executes the first time and repeat only when the expression is true. DO UNTIL loops test the expression after the loop executes at least once and repeat only when the expression is false.
DO WHILE loops in a flowchart appear as follows:
As REXX instructions, the flowchart example looks like:
DO WHILE expression /* expression must be true */
instruction(s)
END
Use a DO WHILE loop when you want to execute the loop while a condition is true. DO WHILE tests the condition at the top of the loop. If the condition is initially false, the language processor never executes the loop.
You can use a DO WHILE loop instead of the DO FOREVER loop in the example of using the LEAVE instruction on page ***. However, you need to initialize the loop with a first case so the condition can be tested before you get into the loop. Notice the first case initialization in the first PULL of the following example.
/******************************** REXX *******************************/
/* This program uses a DO WHILE loop to send a string to a */
/* user-written function for processing. */
/*********************************************************************/
PULL string /* Gets string from input stream */
DO WHILE string \= 'QUIT'
result = process(string) /* Calls a user-written function */
/* to do processing on string. */
IF result = 0 THEN SAY "Processing complete for string:" string
ELSE SAY "Processing failed for string:" string
PULL string
END
SAY 'Program run complete.'
Write a program with a DO WHILE loop that uses as input a list of responses about whether passengers on a commuter airline want a window seat. The flight has 8 passengers and 4 window seats. Discontinue the loop when all the window seats are taken. After the loop ends, produce the number of window seats taken and the number of responses processed.
ANSWER
/******************************** REXX *******************************/
/* This program uses a DO WHILE loop to keep track of window seats */
/* in an 8-seat commuter airline. */
/*********************************************************************/
window_seats = 0 /* Initialize window seats to 0 */
passenger = 0 /* Initialize passengers to 0 */
DO WHILE (passenger < 8) & (window_seats \= 4)
/******************************************************************/
/* Continue while the program has not yet read the responses of */
/* all 8 passengers and while all the window seats are not taken. */
/******************************************************************/
PULL window /* Gets "Y" or "N" from input stream */
passenger = passenger + 1 /* Increase number of passengers by 1 */
IF window = 'Y' THEN
window_seats = window_seats + 1 /* Increase window seats by 1 */
ELSE NOP
END
SAY window_seats 'window seats were assigned.'
SAY passenger 'passengers were questioned.'
DO UNTIL loops in a flowchart appear as follows:
As REXX instructions, the flowchart example looks like:
DO UNTIL expression /* expression must be false */
instruction(s)
END
Use DO UNTIL loops when a condition is not true and you want to execute the loop until the condition is true. The DO UNTIL loop tests the condition at the end of the loop and repeats only when the condition is false. Otherwise, the loop executes once and ends. For example:
/******************************** REXX ******************************/
/* This program uses a DO UNTIL loop to ask for a password. If the */
/* password is incorrect three times, the loop ends. */
/********************************************************************/
password = 'abracadabra'
time = 0
DO UNTIL (answer = password) | (time = 3)
PULL answer /* Gets ANSWER from input stream */
time = time + 1
END
Change the program in the previous exercise on page Exercise - Using a DO WHILE Loop from a DO WHILE to a DO UNTIL loop and achieve the same results. Remember that DO WHILE loops check for true expressions and DO UNTIL loops check for false expressions, which means their logical operators are often reversed.
ANSWER
/******************************** REXX *******************************/
/* This program uses a DO UNTIL loop to keep track of window seats */
/* in an 8-seat commuter airline. */
/*********************************************************************/
window_seats = 0 /* Initialize window seats to 0 */
passenger = 0 /* Initialize passengers to 0 */
DO UNTIL (passenger >= 8) | (window_seats = 4)
/******************************************************************/
/* Continue while the program has not yet read the responses of */
/* all 8 passengers and while all the window seats are not taken. */
/******************************************************************/
PULL window /* Gets "Y" or "N" from input stream */
passenger = passenger + 1 /* Increase number of passengers by 1 */
IF window = 'Y' THEN
window_seats = window_seats + 1 /* Increase window seats by 1 */
ELSE NOP
END
SAY window_seats 'window seats were assigned.'
SAY passenger 'passengers were questioned.'
You can combine repetitive and conditional loops to create a compound loop. The following loop is set to repeat 10 times while the quantity is less than 50, at which point it stops.
quantity = 20
DO number = 1 TO 10 WHILE quantity < 50
quantity = quantity + number
SAY 'Quantity = 'quantity ' (Loop 'number')'
END
The result of this example is as follows:
Quantity = 21 (Loop 1)
Quantity = 23 (Loop 2)
Quantity = 26 (Loop 3)
Quantity = 30 (Loop 4)
Quantity = 35 (Loop 5)
Quantity = 41 (Loop 6)
Quantity = 48 (Loop 7)
Quantity = 56 (Loop 8)
You can substitute a DO UNTIL loop, change the comparison operator from < to >, and get the same results.
quantity = 20
DO number = 1 TO 10 UNTIL quantity > 50
quantity = quantity + number
SAY 'Quantity = 'quantity ' (Loop 'number')'
END
Like nested IF...THEN...ELSE instructions, DO loops can contain other DO loops. A simple example follows:
DO outer = 1 TO 2
DO inner = 1 TO 2
SAY 'HIP'
END
SAY 'HURRAH'
END
The output from this example is:
HIP
HIP
HURRAH
HIP
HIP
HURRAH
If you need to leave a loop when a certain condition arises, use the LEAVE instruction followed by the name of the control variable of the loop. If the LEAVE instruction is for the inner loop, processing leaves the inner loop and goes to the outer loop. If the LEAVE instruction is for the outer loop, processing leaves both loops.
To leave the inner loop in the preceding example, add an IF...THEN...ELSE instruction that includes a LEAVE instruction after the IF instruction.
DO outer = 1 TO 2
DO inner = 1 TO 2
IF inner > 1 THEN
LEAVE inner
ELSE
SAY 'HIP'
END
SAY 'HURRAH'
END
The result is as follows:
HIP
HURRAH
HIP
HURRAH
DO outer = 1 TO 3
SAY /* Produces a blank line */
DO inner = 1 TO 3
SAY 'Outer' outer 'Inner' inner
END
END
DO outer = 1 TO 3
SAY /* Produces a blank line */
DO inner = 1 TO 3
IF inner = 2 THEN
LEAVE inner
ELSE
SAY 'Outer' outer 'Inner' inner
END
END
ANSWERS
Outer 1 Inner 1
Outer 1 Inner 2
Outer 1 Inner 3
Outer 2 Inner 1
Outer 2 Inner 2
Outer 2 Inner 3
Outer 3 Inner 1
Outer 3 Inner 2
Outer 3 Inner 3
Outer 1 Inner 1
Outer 2 Inner 1
Outer 3 Inner 1