For...End for

4D - Documentation   Français   English   German   4th Dimension 2004, Command Theme List   4th Dimension 2004, Command Alphabetical List   4th Dimension 2004, Constant Theme List   Back   Previous   Next

version 6.0


The formal syntax of the For...End for control flow structure is:

   For (Counter_Variable; Start_Expression; End_Expression {; Increment_Expression})
      statement(s)
   End for

The For...End for loop is a loop controlled by a counter variable:

The counter variable Counter_Variable is a numeric variable (Real, Integer, or Long Integer) that the For...End for loop initializes to the value specified by Start_Expression.

Each time the loop is executed, the counter variable is incremented by the value specified in the optional value Increment_Expression. If you do not specify Increment_Expression, the counter variable is incremented by one (1), which is the default.

When the counter variable passes the End_Expression value, the loop stops.

Important: The numeric expressions Start_Expression, End_Expression and Increment_Expression are evaluated once at the beginning of the loop. If these expressions are variables, changing one of these variables within the loop will not affect the loop.

Tip: However, for special purposes, you can change the value of the counter variable Counter_Variable within the loop; this will affect the loop.

Usually Start_Expression is less than End_Expression.

If Start_Expression and End_Expression are equal, the loop will execute only once.

If Start_Expression is greater than End_Expression, the loop will not execute at all unless you specify a negative Increment_Expression. See the examples.

Basic Examples

1. The following example executes 100 iterations:

   For (vCounter;1;100)
      ` Do something
   End for

2. The following example goes through all elements of the array anArray:

   For ($vlElem;1;Size of array(anArray))
         ` Do something with the element
      anArray{$vlElem}:=...
   End for

3. The following example goes through all the characters of the text vtSomeText:

   For ($vlChar;1;Length(vtSomeText))
         ` Do something with the character if it is a TAB
      If (Ascii(vtSomeText[[$vlChar]])=Char(Tab))
         ` ...
      End if
   End for

4. The following example goes through the selected records for the table [aTable]:

   FIRST RECORD([aTable])
   For ($vlRecord;1;Records in selection([aTable]))
         ` Do something with the record
      SEND RECORD([aTable])
         ` ...
         ` Go to the next record
      NEXT RECORD([aTable])
   End for

Most of the For...End for loops you will write in your databases will look like the ones listed in these examples.

Decrementing variable counter

In some cases, you may want to have a loop whose counter variable is decreasing rather than increasing. To do so, you must specify Start_Expression greater than End_Expression and a negative Increment_Expression. The following examples do the same thing as the previous examples, but in reverse order:

5. The following example executes 100 iterations:

   For (vCounter;100;1;-1)
      ` Do something
   End for

6. The following example goes through all elements of the array anArray:

   For ($vlElem;Size of array(anArray);1;-1)
         ` Do something with the element
      anArray{$vlElem}:=...
   End for

7. The following example goes through all the characters of the text vtSomeText:

   For ($vlChar;Length(vtSomeText);1;-1)
         ` Do something with the character if it is a TAB
      If (Ascii(vtSomeText[[$vlChar]])=Char(Tab))
         ` ...
      End if
   End for

8. The following example goes through the selected records for the table [aTable]:

   LAST RECORD([aTable])
   For ($vlRecord;Records in selection([aTable]);1;-1)
         ` Do something with the record
      SEND RECORD([aTable])
         ` ...
         ` Go to the previous record
      PREVIOUS RECORD([aTable])
   End for

Incrementing the counter variable by more than one

If you need to, you can use an Increment_Expression (positive or negative) whose absolute value is greater than one.

9. The following loop addresses only the even elements of the array anArray:

   For ($vlElem;2;((Size of array(anArray)+1)\2)*2;2)
         ` Do something with the element #2,#4...#2n
      anArray{$vlElem}:=...
   End for

Note that the ending expression ((Size of array(anArray)+1)\2)*2 takes care of even and odd array sizes.

Getting out of a loop by changing the counter variable

In some cases, you may want to execute a loop for a specific number of iterations, but then get out of the loop when another condition becomes TRUE. To do so, you can test this condition within the loop and if it becomes TRUE, explicitly set the counter variable to a value that exceeds the end expression.

10. In the following example, a selection of the records is browsed until this is actually done or until the interprocess variable <>vbWeStop, intially set to FALSE, becomes TRUE. This variable is handled by an ON EVENT CALL project method that allows you to interrupt the operation:

   <>vbWeStop:=False
   ON EVENT CALL ("HANDLE STOP")
      ` HANDLE STOP sets <>vbWeStop to True if Ctrl-period (Windows) or Cmd-Period (Macintosh) is pressed
   $vlNbRecords:=Records in selection([aTable])
   FIRST RECORD([aTable])
   For ($vlRecord;1;$vlNbRecords)
         ` Do something with the record
      SEND RECORD([aTable])
         ` ...
         ` Go to the next record
      If (<>vbWeStop)
         $vlRecord:=$vlNbRecords+1 ` Force the counter variable to get out of the loop
      Else
         NEXT RECORD([aTable])
      End if
   End for
   ON EVENT CALL("")
   If (<>vbWeStop)
      ALERT("The operation has been interrupted.")
   Else
      ALERT("The operation has been successfully completed.")
   End if

Comparing looping structures

Let's go back to the first For...End for example:

The following example executes 100 iterations:

   For (vCounter;1;100)
      ` Do something
   End for

It is interesting to see how the While...End while loop and Repeat...Until loop would perform the same action.

Here is the equivalent While...End while loop:

   $i := 1 ` Initialize the counter
   While ($i<=100) ` Loop 100 times
      ` Do something
      $i := $i + 1 ` Need to increment the counter
   End while

Here is the equivalent Repeat...Until loop:

   $i := 1 ` Initialize the counter
   Repeat
      ` Do something
      $i := $i + 1 ` Need to increment the counter
   Until ($i=100) ` Loop 100 times

Tip: The For...End for loop is usually faster than the While...End while and Repeat...Until loops, because 4th Dimension tests the condition internally for each cycle of the loop and increments the counter. Therefore, use the For...End for loop whenever possible.

Optimizing the execution of the For...End for loops

You can use Real, Integer, and Long Integer variables as well as interprocess, process, and local variable counters. For lengthy repetitive loops, especially in compiled mode, use local Long Integer variables.

11. Here is an example:

   C_LONGINT($vlCounter)   ` use local Long Integer variables
   For ($vlCounter;1;10000)
      ` Do something
   End for

Nested For...End for looping structures

You can nest as many control structures as you (reasonably) need. This includes nesting For...End for loops. To avoid mistakes, make sure to use different counter variables for each looping structure.

Here are two examples:

12. The following example goes through all the elements of a two-dimensional array:

   For ($vlElem;1;Size of array(anArray))
         ` ...
         ` Do something with the row
         ` ...
      For ($vlSubElem;1;Size of array(anArray{$vlElem}))
         ` Do something with the element
         anArray{$vlElem}{$vlSubElem}:=...
      End for
   End for

13. The following example builds an array of pointers to all the date fields present in the database:

   ARRAY POINTER($apDateFields;0)
   $vlElem:=0
   For ($vlTable;1;Count table)
      For($vlField;1;Count fields($vlTable))
         $vpField:=Field($vlTable;$vlField)
         If (Type($vpField->)=Is Date)
            $vlElem:=$vlElem+1
            INSERT ELEMENT($apDateFields;$vlElem)
            $apDateFields{$vlElem}:=$vpField
         End if
      End for
   End for

See Also

Case of...Else...End case, Control Flow, If...Else...End if, Repeat...Until, While...End while.


4D - Documentation   Français   English   German   4th Dimension 2004, Command Theme List   4th Dimension 2004, Command Alphabetical List   4th Dimension 2004, Constant Theme List   Back   Previous   Next