1

In the following code, I have tried using a field variable (of class or record) or an array element directly as a loop counter, but this was illegal ("error: invalid index expression"). Is this simply because the loop counter must be a scalar variable?

class Cls {
    var n: int;
}

proc main()
{
    var x = new Cls( 100 );
    var k: [1..10] int;

    for x.n in 1..3 do      // error: invalid index expression
        writeln( x.n );

    for k[1] in 1..3 do     // error: invalid index expression
        writeln( k[1] );
}

On the other hand, if I create a reference to x.n, it compiled successfully but x in the outer scope was not modified. Is this because a new loop variable named n is created in the for-loop? (which I'm afraid is almost the same as my another question...)

proc main()
{
    var x = new Cls( 100 );
    ref n = x.n;

    for n in 1..3 do
        writeln( n );

    writeln( "x = ", x );   // x = {n = 100}
}

If a loop variable is created independently, I guess something like "var x.n = ..." might happen (internally) if I write for x.n in 1..3, which seems really invalid (because it means that I'm trying to declare a loop variable with a name x.n).

roygvib
  • 7,218
  • 2
  • 19
  • 36

1 Answers1

1

You're correct that this relates to your other question. As described there, Chapel's for-loops create new index variables to store the values yielded by the iterator expression(s), so a loop like for i in ... results in a new variable i being declared rather than using an existing variable or expression. If you think the error message should be improved to make this clearer, please consider suggesting a new wording in a GitHub issue.

Note that in addition to single variable names, a loop can also use tuples of index variables to capture the results of a zippered iteration or an iterand that yields tuple values. For instance, the values of the following zippered iteration can either be captured as scalar values i and j:

for (i,j) in zip(1..3, 2..6 by 2) do  // store values in 'i' and 'j' respectively
  writeln((i,j));

or as a single variable of tuple type:

for ij in zip(1..3, 2..6 by 2) do  // store values in 2-tuple 'ij'
  writeln(ij);

Similarly, when iterating over something that yields tuple values, such as a multidimensional index set, the results can be captured either as scalar values or tuples:

const D = {1..3, 0..2};  // declare a 2D rectangular domain

for (i,j) in D do   // store indices in new scalars 'i' and 'j'
  writeln((i,j));

for ij in D do      // store indices in new 2-tuple 'ij'
  writeln(ij);

More complex iterators that return larger, or nested tuples, can similarly be de-tupled or not in the declaration of the index variable(s).

Brad
  • 3,839
  • 7
  • 25
  • Thanks very much, now things are clear to me (i.e., a new loop variable is created for for-loops). By the way, this syntax ("for ij in D do") is one of my most favorite ones in Chapel (because it simplifies multi-dimensional loops :-) I think the error message is no problem because we can understand that it is not allowed (syntactically). – roygvib Apr 20 '18 at 20:48
  • 1
    Yes, the multi-dimensional loop support is pretty great. My favorite example was when a summer intern wrote an AMR framework that was rank-independent so that he could debug it in a 1D run and then run it in production in 2D, 3D, nD, ... (https://github.com/chapel-lang/chapel/tree/master/test/studies/amr) – Brad Apr 20 '18 at 23:51