CftClub.ru
Клуб специалистов ЦФТ-Банк

цикл foreach

 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Уроки ЦФТ-Банк для начинающих
Предыдущая тема :: Следующая тема  
Автор Сообщение
Эмиралька
Эксперт


Вступление в Клуб: 09.11.2015
СообщениеВт Апр 05, 2022 05:41   цикл foreach Ответить с цитатой
Полезность: Нет оценки
-del-

Последний раз редактировалось: Эмиралька (Вт Апр 05, 2022 05:57), всего редактировалось 1 раз
Эмиралька
Эксперт


Вступление в Клуб: 09.11.2015
СообщениеВт Апр 05, 2022 05:52   Re: цикл foreach Ответить с цитатой
Полезность: 4
Эмиралька пишет:
В библиотеке RUNTIME.LIB_MACRO есть замечательный макрос foreach.
его смысл в том, чтобы выполнить обход массива данных.
обычно для этого пишется цикл while, в котором обязательно должен быть индекс, который нужно объявить в начале процедуры. При этом нужно помнить, как индексирован массив, чтобы объявить правильный индекс. В цикле foreach индекс объявляется как параметр макроса без указания типа. Тип определится сам:
Код:

iIdx  integer;
begin
    iIdx := aArray.first;
    while iIdx is not null loop
vs
Код:

    &foreach(aArray, iIdx)


При этом в цикле while обязательно нужно предусматривать сдвиги итератора. Если забудете - можно получить бесконечный цикл. В цикле foreach сдвиг выполняется автоматически:
Код:

iIdx  integer;
begin
    iIdx := aArray.first;
    while iIdx is not null loop
        if условие then
            iIdx := aArray.next(iIdx);
            continue;
        end if;
        iIdx := aArray.next(iIdx);
    end loop;
vs
Код:

    &foreach(aArray, iIdx)
        if условие then
            continue;
        end if;

        -- или даже ещё проще
        &continue_when(условие);
    &end_foreach;


Чтобы прочитать элемент массива в переменную, при использовании стандартных подходов, требуется знать её тип, и, опять же, выполнить это в начале процедуры. При объёме процедуры в сотню строк это очень неудобно. При наличии двух-трёх циклов уже непонятно где какая переменная. В цикле foreach тип знать не нужно, объявление происходит так же в виде параметра:

Код:

iIdx  integer;
recTest rec_test;
begin
    iIdx := aArray.first;
    while iIdx is not null loop
        recTest := aArray(iIdx);
        if условие then
            iIdx := aArray.next(iIdx);
            continue;
        end if;
        iIdx := aArray.next(iIdx);
    end loop;
vs
Код:

begin
    &foreach(recTest in aArray, iIdx)
        if условие then
            continue;
        end if;
    &end_foreach;


Чтобы поменять направление обхода, в цикле while нужно заменить first на last, next на prior, причём в куче мест и не ошибиться - во вложенных циклах этого делать не нужно.
Для foreach достаточно одного ключевого слова:

Код:

iIdx  integer;
recTest rec_test;
iTmp integer;
begin
    iIdx := aArray.last;
    while iIdx is not null loop
        recTest := aArray(iIdx);
        if условие then
            iIdx := aArray.prior(iIdx);
            continue;
        end if;
        iTmp := aArray.next(iIdx);
        while iTmp is not null loop
            iTmp := aArray.next(iTmp);
            debug_pipe(aArray(iTmp).vNum, 0);
        end loop;
        iIdx := aArray.prior(iIdx);
    end loop;
vs
Код:

begin
    &foreach(recTest in reverse aArray, iIdx)
        if условие then
            continue;
        end if;
        &foreach(aArray, iTmp := aArray.next(iIdx))
            debug_pipe(aArray(iTmp).vNum, 0);
        &end_foreach;
    &end_foreach;


Если индексация массива внезапно изменилась и массив стал индексироваться по строке, для цикла while придётся как минимум сменить тип переменной-индекса. Для цикла foreach делать не нужно ничего!
Если начать обход массива нужно не с начала, а с определённой позиции, в цикле foreach это делается элементарно:
Код:

iIdx  varchar2;
recTest rec_test;
begin
    iIdx := aArray.prior('20202');
    while iIdx is not null loop
        recTest := aArray(iIdx);
        if условие then
            iIdx := aArray.prior(iIdx);
            continue;
        end if;
        iIdx := aArray.prior(iIdx);
    end loop;
vs
Код:

begin
    &foreach(recTest in reverse aArray, iIdx := aArray.prior('20202'))
        if условие then
            continue;
        end if;
    &end_foreach;


Параметр-индекс необязателен:
Код:

begin
    &foreach(recTest in aArray)
        continue_when(условие);
    &end_foreach;


за счёт того, что внутри макроса используется begin-end, все переменные, объявленные внутри цикла, переинициализируются на каждой итерации. Область видимости этих переменных - тоже ограничена циклом.

Код:

begin
    &foreach(recTest in aArray)
        continue_when(условие);
        var vNum varchar2;
        vNum := recTest.vNum;
    &end_foreach;


Вот такой интересный макрос.
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Уроки ЦФТ-Банк для начинающих Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru