Функции выполнения циклов
В R 6 появились четыре @-функции, которые реализуют соответственно организацию циклов по счетчику, циклов с пред и постусловием и цикл по элементам списка.
J @For( инициализация_цикла; условие_цикла;
изменение_счетчика; оператор1
[; …; операторN] )
Область применения:
нельзя использовать в формулах отбора, колонок, видимости объекта, редактируемой секции, заголовка окна, всплывающих окон и области размещения.
Осуществляет выполнение цикла по счетчику. Выражение инициализация_цикла
определяет начальное значение счетчика цикла, условие_цикла – выражение, значение которого должно быть 1 (TRUE) – для продолжения вычислений, и 0 (FALSE) – для выхода из цикла, изменение_счетчика – выражение, в котором изменяется счетчик цикла, оператор1, …, операторN
– операторы тела цикла. Общее число операторов цикла не должно превышать 252. Возвращаемое суммарное значение оператора @For есть 1 (TRUE), если ошибок при выполнении не произошло, и ситуация ошибки «unexpected data type» («неожидаемый тип данных»), если условие_цикла на каком-либо шаге вернет нечисловое значение.
Пример 1. Вычисление суммы чисел от 1 до 100.
summa := 0;
rez := @For(i := 1; i <= 100; i := i + 1; summa := summa + i);
@Prompt([OK]; "Инфо"; "Сумма чисел от 1 до 100 = " + @Text( summa ));
REM {выдаст Сумма чисел от 1 до 100 = 5050};
@Prompt([OK]; "Инфо"; @Text( rez ));
REM {выдаст 1}
Из опыта: в теле цикла можно самостоятельно менять переменную цикла; по выходу из цикла значение счетчика сохраняется; если изначально условие цикла не выполняется, то операторы цикла не выполняются. В случае написания бесконечного цикла, система автоматически выполнит выход из «зацикливания», либо по таймауту, либо по переполнению памяти.
В документации сказано, что циклы не предназначены для работы в формулах колонках видов и отбора документов. Однако, опять же из опыта (по крайней мере в R 6.0.1), в этих контекстах они работают. Перед использованием циклов в формулах отбора и колонок (особенно в серверных БД) следует очень хорошо подумать, дабы не «повесить» сервер.
Пример 2. Приведенная ниже формула используется в колонке вида. В документах вида присутствует поле my_num, которое может принимать множественные значения типа число. В формуле колонки вида считается среднеарифметическое значение поля my_num для каждого документа. Следует заметить, что формула работает и при задании для этого столбца сортировок и категоризаций.
summa := 0;
@For(i:=1; i <= @Elements(my_num); i := i + 1; summa := summa + my_num[i]);
summa/@Elements(my_num)
Пример 3. Несколько видоизмененный пример 2. Формула используется в формуле отбора, и отбирает только те документы, у которых среднеарифметическое значение поля my_num больше 10.
summa := 0;
@For(i:=1; i <= @Elements(my_num); i := i + 1; summa := summa + my_num[i]);
select summa/@Elements(my_num) > 10
J @While( условие_цикла; оператор1
[; …; операторN] )
Область применения: нельзя использовать в формулах отбора, колонок, видимости объекта, редактируемой секции, заголовка окна, всплывающих окон, формы и области размещения.
Осуществляет выполнение цикла с предусловием. Выражение условие_цикла
должно принимать значение 1 (TRUE) – для продолжения вычислений, и 0 (FALSE) – для выхода из цикла, оператор1, …, операторN
– операторы тела цикла. Общее число операторов цикла не должно превышать 254. Возвращаемое суммарное значение оператора @While есть 1 (TRUE), если ошибок при выполнении не произошло, и ситуация ошибки «unexpected data type» («неожидаемый тип данных»), если условие_цикла на каком-либо шаге вернет нечисловое значение. Если условие цикла неверно изначально – цикл не выполнится ни разу.
Пример. Вычисление суммы чисел от 1 до 100.
summa := 0;
i := 0;
rez := @While(i < 100; i := i + 1; summa := summa + i);
@Prompt([OK]; "Инфо"; "Сумма чисел от 1 до 100 = " +
@Text( summa ));
REM {выдаст Сумма чисел от 1 до 100 = 5050};
@Prompt([OK]; "Инфо"; @Text( rez ));
REM {выдаст 1}
J @DoWhile( оператор1 ; [ …; операторN;]
условие_цикла )
Область применения: нельзя использовать в формулах отбора, колонок, видимости объекта, редактируемой секции, заголовка окна, всплывающих окон и области размещения.
Осуществляет выполнение цикла с постусловием. Выражение условие_цикла
должно принимать значение 1 (TRUE) – для продолжения вычислений, и 0 (FALSE) – для выхода из цикла, оператор1, …, операторN – операторы тела цикла. Общее число операторов цикла не должно превышать 254. Возвращаемое суммарное значение оператора @DoWhile есть 1 (TRUE), если ошибок при выполнении не произошло, и ситуация ошибки «unexpected data type» («неожидаемый тип данных»), если условие_цикла на каком-либо шаге вернет нечисловое значение. Если условие_цикла неверно изначально – цикл выполнится один раз.
Пример. Вычисление суммы чисел от 1 до 100.
summa := 0;
i := 0;
rez := @DoWhile(i := i + 1; summa := summa + i; i < 100);
@Prompt([OK]; "Инфо"; "Сумма чисел от 1 до 100 = " + @Text( summa ));
REM {выдаст Сумма чисел от 1 до 100 = 5050};
@Prompt([OK]; "Инфо"; @Text( rez ));
REM {выдаст 1}
J @Transform( список; ссылка_на_элемент_списка;
функция )
Область применения: нельзя использовать в формулах отбора, колонок, видимости объекта, редактируемой секции, заголовка окна, всплывающих окон и области размещения.
Осуществляет выполнение цикла по всем элементам списка. Ссылка_на_элемент_списка позволяет в теле функции
обратиться к конкретному элементу списка. Функция
должна возвращать значение для каждого элемента списка. Суммарное возвращаемое значение @Transform и есть список, получившийся поэлементным применением функции к списку. Тип возвращаемого значения @Transform определяется на первой итерации, по типу возвращаемого значения функции на первом элементе списка. Все последующие значения должны быть такого же типа. Если на какой-то итерации функция вернет список, то этот список так же добавится в возвращаемое значение. @Transform возвращает состояние ошибки если на какой-то итерации таковая произошла при выполнении функции. Если на какой-то итерации функция
вернет в качестве значения @Nothing, то этим самым на данной итерации в результирующий список не добавится значения на этой итерации.
Пример. Выровняет все элементы по правому краю, если длина строки больше 5, произойдет усечение до 5-ти символов слева, иначе недостающие слева символы дополнятся символом тире. Переменной b присвоится значение “12345” : ”123--” : ”12---” : ”12345”.
a := " 1234567 ": " 123" : " 12 " : " 12345 ";
b := @Transform( a; "x" ; @If(@Length(@Trim(x)) > 5;
@Left(@Trim(x);5); @Trim(x) +
@Repeat("-"; 5 - @Length(@Trim(x)))));
J @Nothing
Область применения: нельзя использовать в формулах отбора, колонок, видимости объекта, редактируемой секции, заголовка окна, всплывающих окон, формы и области размещения.
В контексте функции @Transform возвращает значение, которое не добавляется в результирующий список. Во всех остальных контекстах возвращает пустую строку.
Пример 1. Изменим пример, относящийся к функции @Transform, таким образом, чтобы в случае, когда исходный элемент списка имел длину больше 5, то такие значения в выходной список не должны попадать. Переменной b присвоится значение ”123--” : ”12---” : ”12345”.
a := " 1234567 " : " 123" : " 12 " : " 12345 ";
b := @Transform( a; "x" ; @If(@Length(@Trim(x)) > 5;
@Nothing; @Trim(x) +
@Repeat("-"; 5 - @Length(@Trim(x)))));
Пример 2. Возвращает 1 (TRUE).
@IsNull(@Nothing);