REPEAT

In this section:

How to:

Reference:

The REPEAT command enables you to loop through a block of code. REPEAT defines the beginning of the block, and ENDREPEAT defines the end. You control the loop by specifying the number of loop iterations, and/or the conditions under which the loop terminates. You can also define counters to control processing within the loop, for example incrementing a row counter to loop through the rows of a stack.

Syntax: How to Use the REPEAT Command

The syntax of the REPEAT command is:

REPEAT {int|ALL|WHILE condition|UNTIL condition} [counter [/fmt] =  
init_expr;] [;]
   command 
   .
   .
   .
ENDREPEAT [counter[/fmt]=increment_expr;...]

where:

int

Specifies the number of times the REPEAT loop is to run. The value of int can be an integer constant, an integer field, or a more complex expression that resolves to an integer value. If you use an expression, the expression should resolve to an integer, although other types of expressions are possible. If the expression resolves to a floating-point or packed-decimal value, the decimal portion of the value will be truncated. If it resolves to a character representation of a numeric value, it will be converted to an integer value.

Expressions are described in Expressions Reference.

ALL

Specifies that the loop is to repeat indefinitely, terminating only when a GOTO EXITREPEAT command is issued from within the loop.

WHILE

Specifies that the WHILE condition is to be evaluated prior to each execution of the loop. If the condition is true, the loop is entered. If the condition is false, the loop terminates and control passes directly to the command immediately following ENDREPEAT. If the condition is false when the REPEAT command is first executed, the loop is never entered.

UNTIL

Specifies that the UNTIL condition is to be evaluated prior to each execution of the loop. If the condition is false, the loop is entered. If the condition is true, the loop terminates and control passes directly to the command immediately following ENDREPEAT. If the condition is true when the REPEAT command is first executed, the loop is never entered.

condition

Is a valid Maintain Data expression that can be evaluated as true or false (that is, a Boolean expression).

counter

Is a variable that you can use as a counter within the loop. You can assign the initial value of the counter in the REPEAT command, or in a COMPUTE command issued prior to the REPEAT command. You can increment the counter at the end of each loop iteration in the ENDREPEAT command. You can also change the value of the counter in a COMPUTE command within the loop. You can refer to the counter throughout the loop, including:

  • Inside the loop, as a stack subscript.
  • Inside the loop, in an expression.
  • In a WHILE or UNTIL condition in the REPEAT command.
fmt

Is the format of the counter. It can be any valid format except for TX. The format is required only if you are defining the variable in this command.

init_expr

Is an expression whose value is assigned to the counter before the first iteration of the loop. It can be any valid Maintain Data expression.

increment_expr

Is an expression whose value is assigned to the counter at the end of each complete loop iteration. It can be any valid Maintain Data expression.

command

Is one or more Maintain Data commands, except for CASE, DECLARE, DESCRIBE, END, MAINTAIN, and MODULE.

;

Terminates the command. If you do not specify a counter, the semicolon is optional but recommended. Including it allows for flexible syntax and better processing. For more information about the benefits of including the semicolon, see Terminating a Command's Syntax.

Example: Simple Loops

The following code has a loop that executes ten or fewer times. The REPEAT line initiates the loop. The number 10 indicates that the loop will run ten times, barring any conditions or commands to exit the loop. The ON NONEXT GOTO EXITREPEAT command causes the loop to be exited when there are no more instances of Sales in the data source. The COMPUTE command calculates TotSales within an execution of the loop. The ENDREPEAT command is the boundary for the loop. Commands after ENDREPEAT are not part of the loop.

Because there is no loop counter, there is no way to know which repetition of the loop is currently executing:

COMPUTE TotSales = 0;
REPEAT 10;
   NEXT Sales;
   ON NONEXT GOTO EXITREPEAT;
   COMPUTE TotSales = TotSales + Sales;
ENDREPEAT

Example: Specifying Loop Iterations

You can control the number of times that the flow of control cycles through the loop by specifying the number of iterations. For example:

REPEAT 27;

You can also specify a condition that must be true or false for looping to continue:

REPEAT WHILE Rows GT 15;

Example: Repeating a Loop a Variable Number of Times

The REPEAT variable construct indicates that the loop is repeated the number of times indicated by the value of the variable. In this example, Stk1 is the name of a stack and FocCount is a stack variable that contains the number of rows in the stack. The loop executes a variable number of times based on the value of Stk1.FocCount:

FOR ALL NEXT Country INTO Stk1;
COMPUTE Cnt/I4 = 1;
REPEAT Stk1.FocCount;
   TYPE "Country = <Stk1(Cnt).Country";
   COMPUTE Cnt = Cnt +1;
ENDREPEAT

Example: REPEAT WHILE and UNTIL

The REPEAT WHILE construct indicates that the loop should be repeated as long as the expression is true. Once the expression is no longer true, the loop is exited. In this example, the loop will be executed Stk1.FocCount number of times. Stk1 is the name of a stack and FocCount is a stack variable that contains the number of rows in the stack:

FOR ALL NEXT Country INTO Stk1;
COMPUTE CNT/I4 = 1;
REPEAT WHILE Cnt LE Stk1.FocCount;
  TYPE "Country = <Stk1(Cnt).Country ";
  COMPUTE Cnt = Cnt + 1;
ENDREPEAT

The REPEAT UNTIL construct indicates that the loop is repeated as long as the expression is not true. Once the expression is true, the loop is exited. In this example, the loop is executed Stk1.FocCount number of times. Stk1 is the name of a stack and FocCount is a stack variable that contains the number of rows in the stack. The COMPUTE increments the counter, although this could have been specified on the ENDREPEAT command. ENDREPEAT indicates the end of the loop:

FOR ALL NEXT Country INTO Stk1;
COMPUTE Cnt/I4 = 1;
REPEAT UNTIL Cnt GT Stk1.FocCount;
   TYPE "Country =  <Stk1(Cnt).Country";
   COMPUTE Cnt = Cnt + 1;
ENDREPEAT

Example: Establishing Counters

You can use as many counters as you need in each loop. The only restriction is that all counter initializations performed in the REPEAT command must fit on the single line of the REPEAT command, and all counter incrementation performed in the ENDREPEAT command must fit on the single line of the ENDREPEAT command. You can avoid the single-line limitation by defining and incrementing counters using COMPUTE commands. It is legitimate, however, to have a REPEAT loop and never refer to any counter within the loop. If this is done, the same row of data is always worked on and unexpected results can occur.

The following examples do not have any index notation on the Stkemp stack, so each NEXT puts data into the same row of the stack. In other words, INTO Stkemp is the same as INTO Stkemp(1). Row one is always referenced because, by default, if there is a stack name without a row number, the default row number of one is used.

REPEAT 10;
   NEXT Emp_ID INTO Stkemp;
   .
   .
   .
ENDREPEAT

is the same as:

REPEAT 10 Cnt/I4=1;
   NEXT Emp_ID INTO Stkemp;
   .
   .
   .
ENDREPEAT Cnt=Cnt+1;

To resolve this problem, the REPEAT loop can establish counters and how they are incremented. Inside the loop, individual rows of a stack can be referenced using one of the REPEAT loop counters. The REPEAT command can be used to initialize many variables that will be used in the loop. For example

REPEAT 100 Cnt/I4=1; Flag=IF Factor GT 10 THEN 2 ELSE 1;

or:

REPEAT ALL Cnt = IF Factor GT 10 THEN 1 ELSE 10;

On the ENDREPEAT command, the counters are incremented by whatever calculations follow the keyword ENDREPEAT. Two examples are

ENDREPEAT Cnt = Cnt + 1; Flag = Flag*2;

and:

ENDREPEAT Cnt=IF Department EQ 'MIS' THEN Cnt+5 ELSE Cnt+1;

The following code sets up a repeat loop and computes the variable New_Sal for every row in the stack. The REPEAT line initiates the loop. The ALL indicates that the loop continues until a command in the loop tells the loop to exit. A GOTO EXITREPEAT command is needed in a loop when REPEAT ALL is used. The Cnt = 1 initializes the counter to 1 the first time through the loop. The COMPUTE command calculates a five percent raise. It uses the REPEAT counter (Cnt) to access each row in the stack one at a time. The counter is checked to see if it is greater than or equal to the number of rows in the Stkemp stack. The stack variable FocCount always contains the value of the number of rows in the stack. After every row is processed, the loop is exited.

The ENDREPEAT command contains the instructions for how to increment the counter:

REPEAT ALL Cnt/I4=1;
   COMPUTE Stkemp(Cnt).NewSal/D12.2=Stkemp(Cnt).Curr_Sal * 1.05;
   IF Cnt GE Stkemp.FocCount THEN GOTO EXITREPEAT;
ENDREPEAT Cnt=Cnt+1;

Example: Nested REPEAT Loops

REPEAT loops can be nested. This example shows one repeat loop nested within another loop. The first REPEAT command indicates that the loop will run as long as the value of A is less than 3. It also initializes the counter A to 1. The second REPEAT command indicates that the nested loop will run until the value of B is greater than 4. It initializes the counter B to 1. Two ENDREPEAT commands are needed, one for each REPEAT command. Each ENDREPEAT increments its respective counters.

REPEAT WHILE A LT 3; A/I4 = 1;
   TYPE "In A loop with A = <A";
   REPEAT UNTIL B GT 4; B/I4 = 1;
       TYPE "   ***In B loop with B = <B ";
   ENDREPEAT B = B + 1;
ENDREPEAT A = A + 1;

The output of these REPEAT loops would look like the following:

In A loop with A = 1
   ***In B loop with B = 1
   ***In B loop with B = 2
   ***In B loop with B = 3
   ***In B loop with B = 4
In A loop with A = 2
   ***In B loop with B = 1
   ***In B loop with B = 2
   ***In B loop with B = 3
   ***In B loop with B = 4

Reference: Usage Notes for REPEAT

The actual number of loop iterations can be affected by other phrases and commands in the loop. The loop can end before completing the specified number of iterations if it is terminated by a WHERE or UNTIL condition, or by a GOTO EXITREPEAT command issued within the loop.

Reference: Commands Related to REPEAT

  • COMPUTE. Is used to define user-defined variables and assign values to existing variables.
  • GOTO. Transfers control to another function or to the end of the current function.

Branching Within a Loop

There are two branching instructions that facilitate the usage of REPEAT and ENDREPEAT to control loop iterations:

Example: Terminating the Loop From the Inside

You can terminate a REPEAT loop by branching from within the loop to outside the loop. When you issue the command GOTO EXITREPEAT, Maintain Data branches to the command immediately following the ENDREPEAT command. It does not increment counters specified in the ENDREPEAT command. For example:

REPEAT ALL;
.
.
.
   GOTO EXITREPEAT;
.
.
.
ENDREPEAT