Aller au contenu

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-ds et dcl-c déclarés dans la procédure ne sont visibles qu'à l'intérieur. static les fait durer d'un appel à l'autre.
Effet
Aucun indicateur ni %FOUND. L'appel renvoie la valeur de return si la procédure déclare un type de retour. Les variables locales sont recréées et réinitialisées à chaque appel, sauf celles marquées static.

À 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.