|
-REPEAT: Looping Made Simple, Made Simple, Made Simple
Do you find yourself repeating code in your FOCEXECs? Or using the "Increment and GOTO" method? If so, you should look at the -REPEAT command in Dialogue Manager as there's a good chance it could help you simplify your code.
All -REPEAT statements require the following:
-REPEAT <loopend label> <Exit Control>
…
-<loopend label> |
You can insert any FOCUS commands you wish between the initial -REPEAT and the -loopend label. FOCUS will execute the commands up to the loopend label, looping back continuously to the -REPEAT statement until the condition expressed in your Exit Control statement is true.
There are three flavors of exit control:
- -REPEAT LOOPEND 5 TIMES
- -REPEAT LOOPEND FOR &VARIABLE FROM 1 TO 10 STEP 2
- -REPEAT LOOPEND WHILE condition
Let's examine how you can use each one.
1. -REPEAT LOOPEND 5 TIMES
The loop is executed a specified number of times. The number can either be a literal or an &variable that evaluates to a number.
You can use this where you know how many times you need to repeat a block of code in which case you will code a literal value in the -REPEAT command. For example, reading the initial lines of a file to extract the header information and write it to a log.
-SET &LINE=' ';
-REPEAT DONELOG 5 TIMES
-READ INFILE &LINE.A80
-WRITE LOGFILE &LINE
-DONELOG |
Or you can use this if you can determine during processing how many times you need to execute the loop, placing the value into an &variable. As in the following, where the end user is asked how many times to run the block of code:
-SET &LINE=' ';
-PROMPT &NUMBER.ENTER THE LINES IN THE FILE HEADER.
-REPEAT DONELOG &NUMBER TIMES
-READ INFILE &LINE.A80.
-WRITE LOGFILE &LINE
-DONELOG |
Instead of prompting for the &NUMBER value, that value could be determined programmatically, meaning that you can use this technique for batch procedures as well as interactive ones.
2. -REPEAT LOOPEND FOR &VARIABLE FROM 1 TO 10 STEP 2
The second flavor of exit control is also based on counting loop repetitions, but in a more controlled way. You can name a counter variable and initialize it outside of the -REPEAT to whatever value you choose. This permits you to specify where to begin counting (FROM n) and how high to go (TO n) and how to count (STEP 1). The count can ascend in single steps or double steps (counting by twos), or descend with negative numbers (STEP -1). It is important to initialize your counter and to make sure that the FROM and TO values match the direction in which you are counting.
Extending the previous example, we want to process the initial lines containing header information differently than the lines that follow. For example, simply TYPE the line with a different identifier.
-SET &LINE=' ';
-SET &LINENUM=0;
-PROMPT &NUMBER.ENTER THE LINES IN THE FILE HEADER.
-REPEAT AFTERLOG FOR &LINENUM FROM 1 TO 100 STEP 1
-READ INFILE &LINE.A80.
-IF &IORETURN NE 0 THEN GOTO DONE;
-IF &LINENUM LE &NUMBER THEN GOTO DOLOG;
-TYPE DATA LINE &LINENUM &LINE
-GOTO AFTERLOG
-DOLOG
-TYPE LOG FILE LINE &LINENUM &LINE
-AFTERLOG
-DONE |
When we use the CAR MASTER file as input, and specify that the first five lines are header information to be indicated as LOG FILE LINES, the result is:
LOG FILE LINE 1 FILENAME=CAR,SUFFIX=FOC
LOG FILE LINE 2 SEGNAME=ORIGIN,SEGTYPE=S1
LOG FILE LINE 3 FIELDNAME=COUNTRY,COUNTRY,A10,FIELDTYPE=I,$
LOG FILE LINE 4 SEGNAME=COMP,SEGTYPE=S1,PARENT=ORIGIN
LOG FILE LINE 5 FIELDNAME=CAR,CARS,A16,$
DATA LINE 6 SEGNAME=CARREC,SEGTYPE=S1,PARENT=COMP
DATA LINE 7 FIELDNAME=MODEL,MODEL,A24,$
DATA LINE 8 SEGNAME=BODY,SEGTYPE=S1,PARENT=CARREC
DATA LINE 9 FIELDNAME=BODYTYPE,TYPE,A12,$
DATA LINE 10 FIELDNAME=SEATS,SEAT,I3,$
DATA LINE 11 FIELDNAME=DEALER_COST,DCOST,D7,$
DATA LINE 12 FIELDNAME=RETAIL_COST,RCOST,D7,$
DATA LINE 13 FIELDNAME=SALES,UNITS,I6,$
DATA LINE 14 SEGNAME=SPECS,SEGTYPE=U,PARENT=BODY
DATA LINE 15 FIELDNAME=LENGTH,LEN,D5,$
DATA LINE 16 FIELDNAME=WIDTH,WIDTH,D5,$
DATA LINE 17 FIELDNAME=HEIGHT,HEIGHT,D5,$
DATA LINE 18 FIELDNAME=WEIGHT,WEIGHT,D6,$
DATA LINE 19 FIELDNAME=WHEELBASE,BASE,D6.1,$
DATA LINE 20 FIELDNAME=FUEL_CAP,FUEL,D6.1,$
DATA LINE 21 FIELDNAME=BHP,POWER,D6,$
DATA LINE 22 FIELDNAME=RPM,RPM,I5,$
DATA LINE 23 FIELDNAME=MPG,MILES,D6,$
DATA LINE 24 FIELDNAME=ACCEL,SECONDS,D6,$
DATA LINE 25 SEGNAME=WARANT,SEGTYPE=S1,PARENT=COMP
DATA LINE 26 FIELDNAME=WARRANTY,WARR,A40,$
DATA LINE 27 SEGNAME=EQUIP,SEGTYPE=S1,PARENT=COMP
DATA LINE 28 FIELDNAME=STANDARD,EQUIP,A40,$ |
3. -REPEAT LOOPEND WHILE Condition
A third flavor of -REPEAT exit control allows you to stop looping based upon a condition that you describe that evaluates to 1 or 0 (true or false). As long as the condition is true, the -REPEAT loop is executed. When the condition is false, the -REPEAT loop stops.
If the processing in the -REPEAT loop includes other statements that also depend upon the contents of the counter, such as loading and validating indexed variable values, or the loop expiration depends on some runtime calculation or event, you may need to use the WHILE control option to manage your looping.
The WHILE option offers broader control over ending your loop, as you are not tied to a counter, but can use a variety of FOCUS expressions for determining whether to continue or exit a loop. You could check the time of day with a subroutine and control a loop with that, or test a variable for a maximum value and exit the loop when that is reached. You could also compare several variables to determine whether or not to stop a loop, or read in a data value from a file and compare it with a literal or other variable to control the loop execution. In each case, you are not tied to a counter a set number of iterations to determine when to finish.
Here’s an example:
-SET &DONE=1;
-SET &PASSNO=0;
-REPEAT LOOPEND WHILE &DONE GT 0 ;
-SET &PASSNO =&PASSNO + 1;
-SET &SCREEN= DECODE &PASSNO (1 'ENGLAND' 2 'AMERICA' 3 'ITALY' ELSE ' ');
-SET &HFILENAME=DECODE &PASSNO (1 'EFILE' 2 'AFILE' 3 'IFILE' ELSE ' ');
TABLE FILE CAR
SUM SALES
BY CAR
BY MODEL
ACROSS SEATS
WHERE COUNTRY EQ '&SCREEN'
ON TABLE HOLD AS '&HFILENAME'
END
-RUN
-SET &DONE=&LINES;
-LOOPEND
-TYPE PROCESSING DONE |
The loop exits after the second pass when zero records were returned from the request, as you can see in this output.
>
NUMBER OF RECORDS IN TABLE= 4 LINES= 4
SEATS
2 4 5
HOLDING...
>
>
NUMBER OF RECORDS IN TABLE= 0 LINES= 0
SEATS
HOLDING...
>
PROCESSING DONE
> |
The &DONE variable is initialized to a positive value, then tested in the -REPEAT statement, and following the TABLE request in the loop, it is set to the value of &LINES, which is tested the next time the -REPEAT is run.The first two flavors of exit control terminated -REPEAT looping based on reaching specified counter values. In case one, we specified a number of TIMES to loop. In case two, we looped a variable number of times based on the &variable value that was incremented or decremented FROM value1 TO value2 in some number (n) of STEPS. In both cases, we counted iterations. The third flavor lets us control the loop exit with an expression of our own choosing, providing a broad range of possibilities.
As you can see, -REPEAT offers many options for simplifying repetitive FOCUS code, and for handling complicated processes. Use your imagination in exploiting this command to see how much time and work it can save you.
|