The Freya Programming Language

For statements

See also

There are two variants of for: on one hand, we have the traditional loop statement from ALGOL and Pascal, which acts on an integer or equivalent local variable. On the other hand, for is also used as the equivalent of the C#'s foreach, for iterating over an IEnumerable aware data structure.

Syntax

This is the syntax for a "traditional" for:

for var-decl := start-expr to-downto end-expr do
    statement

A var-decl defines the control variable in one of these two fashions:

var identifier                 // 1- Type must be inferred.
identifier : type-reference    // 2- Type is explicitly given.

This other for variant is equivalent to the foreach statement in C#, and it iterates over an enumerable data structure:

for var-decl in expression do
    statement

Numerical for statements

The for statement in Freya behaves as the same statement in Delphi and traditional Pascal. It has some similarities with C#'s for, but they differ in several important details:

This loop, for instance, will execute its body 10 times, since 10 is the value of the final expression when the loops begin its execution:

var
    count: Integer := 10;
for var i := 1 to count do
begin
    Console.WriteLine(i);
    count--;
end;

When the final expression is a constant expression, there's no need to generate a temporal variable for holding its initial value. As a consequence, a for loop running against a constant final expression is slightly faster.

There's a variant for the numeric for statement. The above example can be rewritte this way:

var
    count: Integer := 10;
for var i in 1..count do
begin
    Console.WriteLine(i);
    count--;
end;

Though it actually is a for/in statement, it's translated to a numeric for/to statement. The range expression after in is considered a predefined iterator returning all values in the given interval. Please note that an ascending sequence is always produced. You cannot use this variant to simulate a for/downto.

for/in statements

A for/in statement has this syntax:

for var-decl in expression do
    statement

The meaning of the statement depends on the type of the expression after the in keyword. There are five possible situations:

The loop is automatically transformed into a numeric for/to. Since the generated integer control variable is hidden from the programmer and one of the bounds is a constant, the compiler can generate better code than in an explicit numerical for statement.

All items in the array are returned. Control flow is implemented as a series of nested numerical for statements. The outer loops iterates on the leftmost array index.

The type of the expression after the in keyword must provide a function called GetEnumerator, receiving no parameters and return a type from a value with additional constraints. The return type must provide a parameterless function called MoveNext, returning a boolean value, and a Current property.

This pattern allows better code generation for some common cases in the .NET class library. For instance, a class like List[T] implements the IEnumerable[T] interface type, and it could be iterated via this interface. However, this class implements that interface using record types, and calling directly those methods is faster than the standard, IEnumerable[T]-based technique.

The statement calls the GetEnumerator method on the iterator expression, and obtains a generic IEnumerator[T] interface reference. This interface provides a MoveNext method, which is used as the control condition in a while statement. Then, the Current property is called to retrieve a value with type T.

Though this is an efficient technique, most of the times, it performs a little worse than the previously mentioned iteration pattern: it must deal with references, calls are always virtual, and the enumerator object must be disposed when the loop ends.

If the type of the iterator expression doesn't implements IEnumerable[T], but its non generic equivalent IEnumerable, this interface is used to implement the loop. Since IEnumerable.Current returns a value typed as System.Object, a typecast is generated for each step in the iteration. As a consequence, performance is worse than the performance of the generic case.

See also

The Freya Programming Language
Statements
repeat statements
while statements
loop statements
Enumerative types
Iterators