将类型字段或数组元素用作循环计数器无效

Invalid use of a type field or array element as a loop counter

在下面的代码中,我尝试使用字段变量(class 或记录)或数组元素直接作为循环计数器,但这是非法的("error: invalid index expression")。这仅仅是因为循环计数器必须是标量变量吗?

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] );
}

另一方面,如果我创建对 x.n 的引用,它编译成功但外部作用域中的 x 未被修改。这是因为在 for 循环中创建了一个名为 n 的新循环变量吗? (恐怕和我的另一个几乎一样...)

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}
}

如果一个循环变量是独立创建的,我想如果我写 for x.n in 1..3 可能会发生类似 "var x.n = ..." 的事情(内部),这似乎真的无效(因为这意味着我正在尝试声明一个名为 x.n).

的循环变量

你是对的,这与你的. 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有关。

请注意,除了单个变量名称外,循环还可以使用索引变量的元组来捕获压缩迭代或产生元组值的 iterand 的结果。例如,以下压缩迭代的值可以捕获为标量值 ij:

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

或作为元组类型的单个变量:

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

类似地,当迭代产生元组值的东西时,例如多维索引集,结果可以捕获为标量值或元组:

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);

return 更大或嵌套元组的更复杂的迭代器,可以类似地在索引变量的声明中去元组或不去元组。