For

From Free Pascal wiki
Jump to: navigation, search

Deutsch (de) English (en) français (fr) русский (ru)

for is a keyword used in conjunction with other keywords to create loops.

loop with iterator variable

for used along with to/downto and do constructs a loop in which the value of a control variable is incremented or decremented by 1 passing every iteration.

behavior

for controlVariable := start to finalValue do
begin
	statement;
end;

In this example controlVariable is first initialized with the value of start (but cmp. § “legacy” below). If and as long as controlVariable is not greater than finalValue, the beginend block with all its statements is executed. By reaching end controlVariable is incremented by 1 and the comparison is made, whether another iteration, whether the statement-block is executed again.

reverse direction

By exchanging to with downto, the variable – in the example controlVariable – is decremented by 1 and the condition becomes “as long as the control variable is not less than the final value.”

constraints

immutable requirement

While inside in a loop, it is imperative not to mess with the loop variable. Plain assignments – e.g. controlVariable := 2 – are caught by the compiler reporting “Illegal assignment to for-loop variable "controlVariable"”. However, indirect manipulations are not prevented:

program iteratorManipulation(input, output, stderr);
 
var
	i: longint;
 
procedure foo;
begin
	i := 1;
end;
 
begin
	for i := 0 to 2 do
	begin
		writeLn(i);
		foo;
	end;
end.

The global variable i is modified by calling foo. The program runs an infinite loop.

type restrictions

The type of controlVariable has to be enumerable. Assuming your system operates on ASCII you can do

var
	c: char;
begin
	for c := 'a' to 'z' do
	begin
		writeLn(c);
	end;
end.

or generally use any type that is enumerable.

other step widths

Other step widths than 1 or -1 are not possible by utilizing this syntax. You have to use other loop constructs such as while … do and manually initialize, compare and change the controlVariable.

The matter, whether FreePascal could provide a syntax specifying other step widths, came up several times. In general it was regarded as “syntactic sugar”, though, and in order to stay compatible Pascal's core, or Delphi's extensions, in order to avoid any impetuous decisions, the developers remained rather conservative and rejected any changes in that direction.

limits

Note, as it is common mathematics when writing sums [math]\sum_{n=0}^{k}[/math] or products [math]\prod_{n=1}^{k}[/math] the limits are inclusive.

for i := 5 to 5 do
begin
	writeLn(i);
end;

This excerpt will print one line with 5, though you might be fooled by such thoughts as “5 to 5 – that's zero. The body must never be executed.”

legacy

Assuming no other manipulations were made, after the loop the value of controlVariable will be final, unless the the proper condition was not met from the start, then it is undefined (remains unchanged).

In case of empty loops (where the body is never executed), even the start value is not loaded. Rationale: The controlVariable exists for usage inside the loop's body. If the loop's body is not entered, then the value might remain unused. We generally avoid unused values, i.e. any unnecessary assignment without successive reads.

short syntax

For single statements writing a surrounding begin … end block can be skipped resulting in:

for controlVariable := start to final do
	statement;

It is advised though, to make use of that only in justified cases, where the readability is improved and it is very unlikely the loop is expanded by any additional statement. Too many programmers inadvertently fell for the pitfall before and added a properly indented line forgetting it requires a surrounding begin … end then, too.

Make it a habit and always accompany for-loops with begin … end, leaving the option to possibly eliminate those at a later stage (but not during development).

loop with elements

With forin loops the variable that is changed every iteration represents an element out of a collection.

type
	furniture = (chair, desk, bed, wardrobe);
	arrangement = set of furniture;
var
	thing: furniture;
begin
	writeLn('all available pieces of furniture:');
	for thing in arrangement do
	begin
		writeLn(thing);
	end;
end.

In contrast to other loops, an index variable is not provided. In the above example ord(thing) will return an index, but it has to be additionally retrieved while it inherently exists yet still inaccessible. Proposals were made, whether and how to extend the syntax allowing to specify an index variable that is adjusted with every iteration.

see also


Keywords: begindoelseendforifrepeatthenuntilwhile