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

时间:2018-04-20 20:03:43

标签: chapel

在下面的代码中,我尝试将字段变量(类或记录)或数组元素直接用作循环计数器,但这是非法的(“错误:无效的索引表达式”)。这只是因为循环计数器必须是标量变量吗?

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的新循环变量吗? (我害怕与我的另一个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}
}

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

1 个答案:

答案 0 :(得分:1)

这是正确的,这与您的other question有关。如上所述,Chapel的for循环创建新的索引变量来存储迭代器表达式产生的值,因此像for i in ...这样的循环会导致声明一个新变量i而不是使用现有变量或表达式。如果您认为应该改进错误消息以使其更清楚,请考虑在GitHub issue中建议新的措辞。

请注意,除了单个变量名之外,循环还可以使用索引变量的元组来捕获zippered迭代的结果或产生元组值的迭代。例如,以下zippered迭代的值可以作为标量值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);

返回更大或嵌套元组的更复杂的迭代器可以类似地在索引变量的声明中被解除或不被解除。