Программирование на языке «Ядро»: Руководство пользователя, страница 8

В этом случае неопределенное значение повторителя (правого аргумента операций repeat и repscal) генерирует последовательность неопределенной длины, которая выравнивается по длине левой части.

Заметим, что вместо использования массивов X и Y можно было бы задать последовательность явно (в скобках), если M и N достаточно невелики:

XYZ[,1]:=(0, 1, 2, 3, 4) repeat;

XYZ[,2]:=( 0, 1, 2, 3, 4) repscal;

Разумеется, интерпретатор не всегда может правильно определить длину последовательности с пустым повторителем. Укажем правила, по которым должна строиться такая последовательность.

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

1 repscal, (2, 3) repeat 10

содержит один участок неопределенной длины, и путем выбора значения пустого повторителя она может получить любую нужную длину, причем требуемое значение повторителя однозначно определяется длиной. Если же мы не укажем значения второго повторителя:

1 repscal, (2, 3) repeat;

то длина последовательности не однозначно определяет значения обоих повторителей. Поэтому такая последовательность будет недопустимой.

Правильность последовательности неопределенной длины синтаксически не проверяется. Если последовательность ошибочна, то это устанавливается при её интерпретации (выполнении оператора) и вызывает сообщение об ошибке.

1.4.5. Прогрессии

Часто встречающимся видом регулярности данных является их построение по закону арифметической или геометрической прогрессии. Например, координаты узлов равномерной сетки на рисунке 8 подчиняются закону арифметической прогрессии: абсцисса каждого узла больше абсциссы соседнего узла слева на величину шага hx, ордината – больше ординаты соседнего узла снизу на величину шага hy. На языке «Ядро» присваивание значений координат узлов равномерной сетки можно было бы записать с помощью арифметических прогрессий:

XYZ[,1]:=(0 by hx numb N) repeat;

XYZ[,2]:=(0 by hy numb M)repscal;

При этом указаны начальное значение, шаг и число членов прогрессии.

Для построения арифметической прогрессии в языке имеются инфиксные операции:

by – задает шаг прогрессии;

numb – задает длину прогрессии;

to – задает предел прогрессии.

Запись прогрессии должна содержать ровно две из них, причём в любом порядке. Если заданы шаг и число членов, то предел определяется автоматически; если задан шаг и предел, то автоматически определяется длина; если задан предел и длина, то автоматически определяется шаг. Если шаг не задан и не определяется автоматически, то он принимается равным единице. В остальных случаях операнды либо недостаточны, либо противоречивы, что вызывает сообщение об ошибке. Например, следующие записи равносильны:

1 to 5 by 1

1 numb 5 by 1

1 to 5 numb 5

1 to 5

1 numb 5

Для построения геометрической прогрессии используется операция mult, задающая знаменатель прогрессии, и уже рассмотренная выше операция numb. Все другие варианты задания геометрической прогрессии невозможны. Например, запись 1 mult 2 numb 5 изображает геометрическую прогрессию: (1, 2, 4, 8, 16).

Прогрессии могут строиться не только из скаляров. Как начальные значения, так и шаг, предел или знаменатель прогрессии сами могут быть последовательностями одинаковых длин. Приведенный выше пример задания координат сетки можно было бы записать так:

XYZ[,(1,2)]:=((0,0) by (hx,0) numb N) by ((0,hy) repeat N) numb M;

Здесь записаны две арифметические прогрессии. Первая из них начинается с координат начального узла (0, 0) и задает координаты первого горизонтального ряда из N узлов, прибавляя каждый раз к координатам предыдущего узла вектор (hx, 0). Вторая начинается с полученной прогрессии, её шагом является повторенная N раз последовательность (0, hy), а число повторений равно числу горизонтальных рядов.

Вообще говоря, длины всех последовательностей – полей прогрессий – должны совпадать. Однако язык «Ядро» допускает следующие исключения из этого правила.

Скалярное поле считается повторяющимся столько раз, сколько необходимо. Например, запись (1, 1) by 2 numb 5 равносильна записи (1, 1) by (2, 2) numb 5.

Последовательности в записи шага (by), начального члена, предела (to) и знаменателя (mult) и длины прогрессии (numb) дополняются единицами до длины максимальной из них с выдачей предупреждения о возможной ошибке. Например, выражение (0, 0) by (1,1,1) numb 2 преобразуется в (0, 0, 1) by (1, 1, 1) numb 2.

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

Если последовательность в поле numb – не скалярная, то из неё берется наименьшее значение. Пример: выражение (0, 0) by (1, 1) numb (2, 3) равносильно (0, 0) by (1, 1) numb 2. Вообще, прогрессия заканчивается, когда заканчивается самая короткая из последовательностей, заданных скалярными компонентами; например, выражение (0, 0) to (3, 5) by 1 задает последовательность (0, 0, 1, 1, 2, 2, 3, 3).

1.4.5. Целочисленные прогрессии

Целочисленные прогрессии с шагом 1 могут задаваться с помощью инфиксной операции – двоеточия (:), которое отделяет начальное значение от конечного. По умолчанию начальное значение равно единице. Если конечное значение не задано, то получается прогрессия неопределенной длины; она выравнивается интерпретатором по контексту.

Чаще всего такие прогрессии используются в индексных выражениях для задания диапазона изменения индекса. Например, выражение XYZ[2:5] означает последовательность компонент массива XYZ со 2-й по 5-ю включительно; XYZ[2:M-1, 2:N-1,:2] – последовательность первых двух координат тех узлов сетки на рисунке 8, которые не лежат на границе области (первые два индекса, которые изменяются в пределах от 2 до предпоследнего значения, означают номера горизонтальных и вертикальных рядов узлов). Если в индексной позиции не указано значение после двоеточия, то предполагается значение границы по соответствующему измерению: XYZ[2:, 2:, ] равносильно выражению XYZ[2:M, 2:N, 1:3].

Вне индексных позиций целочисленная прогрессия неопределенной длины выравнивается по обычным правилам. Поэтому её можно использовать для нумерации элементов массивов. Пусть, например, описан целочисленный массив NG[M,N]. Оператор NG:=1:; помещает в каждую компоненту массива её номер. Такая запись удобна тем, что не зависит от размеров массива.