Como criar um subprograma recursivo em Cobol?

Para criar um subprograma recursivo (um subprograma que chama a si mesmo) devemos utilizar a opção “IS RECURSIVE” no PROGRAM-ID e atentar para alguns detalhes.

O subprograma a seguir mostra o tradicional cálculo de fatorial, utilizado por dez em cada dez programadores que querem dar exemplos de recursividades.

Só para recordar…

5! = 5 x 4 x 3 x 2 x 1 = 120

…que é a mesma coisa que escrever…

5! = 5 x 4!

Ou seja, uma das propriedades do fatorial é que…

n! = n x (n - 1)!

…então vamos codificar um subprograma que subtrai 1 do argumento recebido e chama a si mesmo com esse novo argumento:

identification division.
program-id. FATORIAL is recursive.

data division.
working-storage section.
01 wt-n-1 pic 9(009) value zeros.
01 wt-fatorial pic 9(009) value zeros.
01 wt-fatorial-1 pic 9(009) value zeros.

linkage section.
01 lk-n pic 9(009) value zeros.

procedure division using lk-n returning wt-fatorial.
inicio.
    if lk-n = 1 
        move 1 to wt-fatorial 
    else 
        compute wt-n-1 = lk-n - 1 
        call "FATORIAL" using by content wt-n-1 
                        returning wt-fatorial-1 
        compute wt-fatorial = lk-n * wt-fatorial-1 
    end-if 
    goback.

Repare que o subprograma chama a si mesmo passando o valor do argumento recebido (lk-n) menos 1 e em seguida multiplica o argumento original pelo resultado do CALL.

O programa chamador…

identification division.
program-id. gtc002.

data division.
working-storage section.
77 wt-n pic 9(009) value zeros.
77 wt-fatorial pic 9(009) value zeros.

procedure division.
main.
    display "Entre com um numero inteiro positivo:"
    accept wt-n from console
    call "FATORIAL" using wt-n returning wt-fatorial
    display wt-n "!=" wt-fatorial
    stop run.

…mostra a seguinte mensagem quando é executado:

[aeisxpad ~/cbl]$ gtc002
Entre com um numero inteiro positivo:
5
000000005!=000000120

Alguns detalhes que reparei enquanto estava codificando os programas é que as variáveis de resultado não devem fazer parte da linkage (por isso a opção RETURNING tanto na PROCEDURE DIVISION do subprograma quanto no CALL.

Além disso, só deu certo depois que coloquei a cláusula BY CONTENT no CALL dentro do subprograma. Diferentemente da opção BY REFERENCE (default), a opção BY CONTENT faz com que o programa chamador passe para o programa chamado o endereço de memória de uma cópia do argumento (e não o endereço de memória do argumento em si). Com isso, na prática, estamos isolando as variáveis das diversas instâncias de FATORIAL que são criadas durante a execução do programa principal.


Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *