Недопустимое использование поля типа или элемента массива в качестве счетчика цикла

В следующем коде я попытался использовать переменную поля (класса или записи) или элемент массива непосредственно в качестве счетчика цикла, но это было недопустимо ("ошибка: недопустимое выражение индекса"). Это просто потому, что счетчик циклов должен быть скалярной переменной?

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

Если переменная цикла создается независимо, я предполагаю, что что-то вроде "var x.n =..." может произойти (внутри), если я напишу for x.n in 1..3, что кажется действительно недействительным (потому что это означает, что я пытаюсь объявить переменную цикла с помощью имя x.n).


person roygvib    schedule 20.04.2018    source источник


Ответы (1)


Вы правы, что это относится к вашему другому вопросу. Как описано там, циклы for в Chapel создают новые индексные переменные для хранения значений, выдаваемых выражениями итератора, поэтому цикл, подобный for i in ..., приводит к объявлению новой переменной i, а не к использованию существующей переменной или выражения. Если вы считаете, что сообщение об ошибке следует улучшить, чтобы сделать его более понятным, рассмотрите возможность предложения новой формулировки в Проблема с GitHub.

Обратите внимание, что в дополнение к именам отдельных переменных цикл также может использовать кортежи индексных переменных для захвата результатов заархивированной итерации или итерации, которая дает значения кортежа. Например, значения следующей сжатой итерации могут быть захвачены как скалярные значения i и j:

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

Более сложные итераторы, которые возвращают большие или вложенные кортежи, могут быть аналогичным образом разделены или нет в объявлении переменных индекса.

person Brad    schedule 20.04.2018
comment
Большое спасибо, теперь мне все ясно (т.е. для for-loops создается новая переменная цикла). Кстати, этот синтаксис (для ij в D do) — один из моих самых любимых в Chapel (потому что он упрощает многомерные циклы :-). Я думаю, что сообщение об ошибке не проблема, потому что мы можем понять, что это не разрешено. (синтаксически). - person roygvib; 20.04.2018
comment
Да, поддержка многомерных циклов довольно хороша. Мой любимый пример: летний стажер написал фреймворк AMR, не зависящий от ранга, чтобы он мог отлаживать его в одномерном прогоне, а затем запускать в продакшене в двухмерном, трехмерном, многомерном, ... (github.com/chapel-lang/chapel/tree/master/test/studies/amr< /а>) - person Brad; 21.04.2018