Pull to refresh

Comments 7

Поинтересуюсь: а сейчас подпрограммы - рекурсивные? (Когда появился RPG, аппаратного стека не было, и адрес возврата записывался в фиксированное место в памяти, что приводило к зацикливанию программы при рекурсивных вызовах.)

Честно скажу -не знаю. Не задумывался об этом и не пробовал.

Надо будет попробовать ради интереса.

Одну подпрограмму из другой вызвать не проблема. Т.е. какой-то стек точек возврата там есть.

Можно ли сабрутину саму из себя вызвать - не знаю...

Не только саму из себя, кстати. Может ещё быть косвенная рекурсия, самый сложный вариант для поиска ошибки, когда не организован полноценный стек вызовов-возвратов.

Ну в рекурсиях вообще ошибки сложнее искать.

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

Одно время было модно делать выход из процедуры через сабрутину - такая единая точка выхода которую можно из любого места процедуры вызывать. Сейчас не актуально т.к. появился on-exit и можно просто ставить return где надо, а в точке выхода уже всю необходимую финализацию делать.

Так что сабрутины сейчас на второй план отшли.

Так и осталось

Пробуем

        dcl-s recLevel          int(5);
        dcl-s counter           int(5)  inz(5);

        exsr srRecursion;
        return;
      
        begsr srRecursion;
          recLevel += 1;
          dsply ('Recursion Level - ' + %char(recLevel));
          dsply ('Counter         - ' + %char(counter));
          
          if counter > 0;
            counter -= 1;
            exsr srRecursion;
          endif;
          
          recLevel -= 1;
          dsply ('Recursion Level - ' + %char(recLevel));
        endsr;

Не компилируется - *RNF7112 30 EXSR or CASxx in subroutine SRRECUR... calls the same subroutine; the specification is ignored.

Пытаемся обмануть

        dcl-s recLevel          int(5);
        dcl-s counter           int(5)  inz(5);

        exsr srRecCall;
        return;
      
        begsr srRecCall;
          recLevel += 1;
          dsply ('Recursion Level - ' + %char(recLevel));
          
          exsr srRecursion;

          recLevel -= 1;
          dsply ('Recursion Level - ' + %char(recLevel));
        endsr;
        
        begsr srRecursion;
          dsply ('Counter         - ' + %char(counter));
          
          if counter > 0;
            counter -= 1;
            exsr srRecCall;
          endif;
        endsr;

Так компилируется, но...

DSPLY Recursion Level - 1
DSPLY Counter - 5
DSPLY Recursion Level - 2
DSPLY Counter - 4
DSPLY Recursion Level - 3
DSPLY Counter - 3
DSPLY Recursion Level - 4
DSPLY Counter - 2
DSPLY Recursion Level - 5
DSPLY Counter - 1
DSPLY Recursion Level - 6
DSPLY Counter - 0
DSPLY Recursion Level - 6
DSPLY Recursion Level - 5
DSPLY Recursion Level - 4
DSPLY Recursion Level - 3
DSPLY Recursion Level - 2
DSPLY Recursion Level - 1
DSPLY Recursion Level - 0
DSPLY Recursion Level - -1
DSPLY Recursion Level - -2
...

И дальше только ENDJOB помогает.

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

Sign up to leave a comment.

Articles