progress-4gl

Iterating

Introduction#

There are several ways of iterating (looping) in Progress ABL.

DO WHILE

A DO WHILE loop will continue to loop unless the WHILE-part is met. This makes it easy to run forever and eat up all time from one CPU core.

DO WHILE expression:

END.

expression is any combination of boolean logic, comparisons, variables, fields etc that evaluates to a true value.

/* This is a well defined DO WHILE loop that will run as long as i is lower than 10*/
DEFINE VARIABLE i AS INTEGER     NO-UNDO.
DO WHILE i < 10:
    i = i + 1.
END.

DISPLAY i. // Will display 10

You can use any number of checks in the WHILE-part:

DEFINE VARIABLE i AS INTEGER     NO-UNDO.
DO WHILE TODAY = DATE("2017-02-06") AND RANDOM(1,100) < 99:
    i = i + 1.
END.

MESSAGE i "iterations done" VIEW-AS ALERT-BOX.

However, the compiler wont help you so check that the WHILE-part eventually is met:

/* Oops. Didnt increase i. This will run forever... */
DEFINE VARIABLE i AS INTEGER     NO-UNDO.
DO WHILE i < 10:
    i = 1.
END.

DO var = start TO finish [BY step]

This iteration changes a value from a starting point to an end, optionally by a specified value for each step. The default change is 1.

DEFINE VARIABLE i AS INTEGER     NO-UNDO.

DO i = 10 TO 15:
    DISPLAY i WITH FRAME x1 6 DOWN .
    DOWN WITH FRAME x1.
END.

Result:

---------------i

        10
        11
        12
        13
        14
        15

You can iterate over dates as well:

DEFINE VARIABLE dat AS INTEGER        NO-UNDO.

DO dat = TODAY TO TODAY + 3:

END.

And over decimals. But then you most likely want to use BY - otherwise an INTEGER would have done just as fine…

DEFINE VARIABLE de AS DECIMAL     NO-UNDO.

DO de = 1.8 TO 2.6 BY 0.2:
    DISPLAY "Value" de.
END.

Using BY a negative number you can also go from a higher to a lower value:

DEFINE VARIABLE i AS INTEGER     NO-UNDO.

DO i = 5 TO 1 BY -1:
    
END.

The expression will be tested until it’s no longer met. This makes the counter be higher (if moving upwards) or lower (if moving downwards) once the loop is finished:

DEFINE VARIABLE i AS INTEGER     NO-UNDO.

DO i = 5 TO 1 BY -1:
    
END.

MESSAGE i. // Will message 0

Another example:

DEFINE VARIABLE da AS DATE     NO-UNDO.

DISPLAY TODAY. //17/02/06
DO da = TODAY TO TODAY + 10:
    
END.
DISPLAY da. //17/02/17 (TODAY + 11)

REPEAT

REPEAT, will repeat itself forever unless you explicitly exit the loop:

//Runs forever
REPEAT:
    // Do stuff
END.

To exit the loop you can use the LEAVE keyword. With or without a label. Without a label LEAVE will always effect the current loop. With a name you can specify what loop to LEAVE.

/* Without a label */
REPEAT:
  //Do stuff
  IF TRUE THEN LEAVE.
END.

/* With a label */
loopLabel:
REPEAT:
  //Do stuff
  IF <somecondition> THEN LEAVE loopLabel.
END.

/* Two nested REPEATS */
DEFINE VARIABLE i AS INTEGER     NO-UNDO.
loopLabelOne:
REPEAT:
    loopLabelTwo:
    REPEAT:
        i = i + 1.
        IF RANDOM(1,100) = 1  THEN LEAVE loopLabelTwo.
        IF RANDOM(1,100) = 1  THEN LEAVE loopLabelOne.
    END.
    IF RANDOM(1,100) = 1  THEN LEAVE loopLabelOne.
END.
DISPLAY i.

This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow