Instruction RPG full free · IBM i (AS/400) · Déclarations
DCL-PROC
Déclarer une procédure
Définit une procédure : un bloc de code réutilisable, avec ses paramètres, ses variables locales et éventuellement une valeur de retour.
Syntaxe
dcl-proc nom;
dcl-pi *n [type de retour]; … end-pi;
déclarations locales
instructions
[return valeur;]
end-proc;
nom- Le nom de la procédure. C'est celui qu'on utilise pour l'appeler.
dcl-pi … end-pi- L'interface : les paramètres et le type de retour. Absente si la procédure n'a ni paramètre ni retour.
variables locales- Les
dcl-s,dcl-dsetdcl-cdéclarés dans la procédure ne sont visibles qu'à l'intérieur.staticles fait durer d'un appel à l'autre. - Effet
- Aucun indicateur ni %FOUND. L'appel renvoie la valeur de
returnsi la procédure déclare un type de retour. Les variables locales sont recréées et réinitialisées à chaque appel, sauf celles marquéesstatic.
À quoi ça sert
Les procédures sont la brique de base d'un programme moderne : un calcul de TVA, une mise en forme, un contrôle de saisie s'écrivent une fois et s'appellent depuis partout. Elles remplacent les sous-routines (begsr) avec de vrais paramètres, des variables locales, et la récursivité.
Dans un programme à cycle ou à procédure principale, les procédures se placent après la fin du code principal. Chacune est précédée de son prototype (dcl-pr). Les variables locales protègent du risque de modifier par erreur une variable globale du même nom.
Exemple 1 : Variables locales, appels dans une expression, récursivité
**free
// DCL-PROC : une procedure a ses propres variables, invisibles du reste du programme.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s total packed(9:2) inz(10);
dcl-pr moyenne packed(9:2);
a packed(9:2) const;
b packed(9:2) const;
end-pr;
dcl-pr factorielle uns(20);
n uns(3) value;
end-pr;
snd-msg 'Moyenne de 1250,50 et 45,10 : ' + %char(moyenne(1250.50 : 45.10));
snd-msg 'Total global apres appel : ' + %char(total);
snd-msg '5! = ' + %char(factorielle(5)) + ' ; 10! = ' + %char(factorielle(10));
*inlr = *on;
dcl-proc moyenne;
dcl-pi *n packed(9:2);
a packed(9:2) const;
b packed(9:2) const;
end-pi;
dcl-s total packed(9:2);
total = a + b;
return total / 2;
end-proc;
dcl-proc factorielle;
dcl-pi *n uns(20);
n uns(3) value;
end-pi;
if n <= 1;
return 1;
endif;
return n * factorielle(n - 1);
end-proc;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Moyenne de 1250,50 et 45,10 : 647.80
Total global apres appel : 10.00
5! = 120 ; 10! = 3628800
moyenne a sa propre zone total : le total global du programme reste à 10,00 après l'appel. factorielle s'appelle elle-même : 5! = 120, 10! = 3 628 800 (affiché sans séparateur).
Exemple 2 : Variable locale ou STATIC
**free
// DCL-PROC : une variable locale est reinitialisee a chaque appel; STATIC garde sa valeur.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-pr compter int(10) end-pr;
dcl-pr compterStatique int(10) end-pr;
dcl-s i int(5);
for i = 1 to 3;
snd-msg 'Appel ' + %char(i) + ' : local = ' + %char(compter())
+ ', static = ' + %char(compterStatique());
endfor;
*inlr = *on;
dcl-proc compter;
dcl-pi *n int(10) end-pi;
dcl-s nb int(10) inz(0);
nb += 1;
return nb;
end-proc;
dcl-proc compterStatique;
dcl-pi *n int(10) end-pi;
dcl-s nb int(10) inz(0) static;
nb += 1;
return nb;
end-proc;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Appel 1 : local = 1, static = 1
Appel 2 : local = 1, static = 2
Appel 3 : local = 1, static = 3
Les deux procédures incrémentent un compteur. La variable locale repart à zéro à chaque appel et renvoie toujours 1 ; la variable static garde sa valeur et renvoie 1, 2, 3.
Le piège
Une variable locale est réinitialisée à chaque appel. Dans l'exemple 2, compter renvoie 1 à chaque fois : le nb local repart à sa valeur inz à chaque appel. Pour un compteur, un cache, une valeur à retenir entre deux appels, ajoutez static.
L'inverse existe aussi : une variable locale du même nom qu'une variable globale la masque. Dans l'exemple 1, le total de moyenne n'a rien à voir avec le total du programme (10,00 avant et après). Pratique pour l'isolement, déroutant si on voulait modifier la globale.