|
|
|
|
|
- Principe
- Déclaration et appel des procédures internes
- Caractéristiques des procédures internes
- Utilisation en callback
- Paramètre de type Procédure interne
- Accès aux variables depuis une procédure interne
- Imbrication de procédures internes
- Procédures internes soeurs
- Appels récursifs
- Paramètres nommés
- Compilation dynamique
- Procédure interne et attributs d'extension
- Cas particulier : Utilisation de procédures internes avec des fonctions asynchrones
- Limitations
De nombreuses fonctionnalités nécessitent une procédure appelée une ou plusieurs fois au travers d'une fonction du WLangage (également appelée "Callback"). Par exemple, les fonctions suivantes sont dans ce cas : fListeFichier, ArbreListeFils, AlbumSélecteur en iOS, etc. Il est nécessaire de créer une procédure pour ces fonctions, mais de nombreux inconvénients apparaissent : - Perte de la localité du code : Il n'est pas possible de voir l'algorithme final dans son ensemble. Il est nécessaire de faire des aller-retour entre le code appelant et la procédure WLangage.
- Difficulté de partage d'informations avec la procédure WLangage : Il est en général nécessaire d'utiliser des variables globales (pour passer des paramètres à la callback ou récupérer les résultats).
Dans ce cas, les procédures internes permettent de simplifier l'écriture des fonctionnalités à callback et de simplifier les problèmes posés par l'utilisation d'une procédure classique. Déclaration et appel des procédures internes La déclaration d'une procédure interne se fait directement dans le code d'un traitement existant (traitement associé à un champ, procédure de fenêtre, procédure globale ou méthode de classe, ...). La syntaxe est la suivante :
PROCEDURE INTERNE <Nom de la procédure>() <Code de la procédure> FIN Remarques : - Les procédures internes doivent être déclarées dans le traitement dans lequel elles sont utilisées.
- L'assistance à la saisie des paramètres est activée : une bulle d'aide précisant le type du paramètre attendu est affichée lors de la saisie de l'appel de la procédure interne.
- Le code du traitement situé avant et après le code de déclaration de la procédure interne est exécuté en séquence : le code de la procédure interne n'est pas exécuté.
Exemple :
// Code avant la procédure Interne : Ce code est exécuté. PROCÉDURE INTERNE MaProcédureInterne() // Code de la procédure interne. // Ce code n'est pas exécuté. FIN // Code après la procédure interne : Ce code est exécuté.
- Il est possible d'appeler directement une procédure interne par son nom, comme pour une procédure classique. Cet appel peut être placé avant ou après la déclaration de la procédure interne.
Exemple :
// Appel placé avant MaProcédureInterne()  // Déclaration de la procédure interne PROCÉDURE INTERNE MaProcédureInterne() // Code de la procédure interne exécuté lors de l'appel à MaProcédureInterne() FIN  // Appel placé après MaProcédureInterne()
Il est ainsi possible d'obtenir un code plus simple à lire. - Les exceptions provoquées par les procédures internes peuvent être traitées à l'extérieur de la procédure interne.
Caractéristiques des procédures internes Utilisation en callback La procédure interne peut être utilisée dans une fonction du WLangage qui attend une procédure WLangage en paramètre (comme fListeFichier, ArbreListeFils, ...). Attention : Dans ce cas, le paramètre correspondant au nom de la procédure interne doit correspondre directement au nom de la procédure interne (le nom de la procédure ne doit pas être entre guillemets). Ne pas faire :
// Liste les "fils" du noeud "Desserts" dans le champ Arbre "ARBRE_RecetteTV" Res = ArbreListeFils(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", "DérouleTout")  PROCÉDURE INTERNE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur) ... FIN
Faire :
// Liste les "fils" du noeud "Desserts" dans le champ Arbre "ARBRE_RecetteTV" Res = ArbreListeFils(ARBRE_RecetteTV, "Recettes" + TAB + "Desserts", DérouleTout)  PROCÉDURE INTERNE DérouleTout(ARBRE_RecetteTV, CheminFils, FilsTrouvé, Niveau, Pointeur) ... FIN
Paramètre de type Procédure interne La procédure interne peut être utilisée comme paramètre dans une procédure. Dans ce cas le type du paramètre sera de type "Procédure". Exemple :
// Déclaration de la procédure interne PROCÉDURE INTERNE MaProcédureInterne() // code exécuté lors de l'appel de la procédure passée en paramètre FIN  MonAutreProcédure(MaProcédureInterne)
PROCÉDURE MonAutreProcédure(p est une procédure)  p()
Accès aux variables depuis une procédure interne Les variables déclarées dans le même traitement que la déclaration de la procédure interne peuvent être appelées dans la procédure interne. Il n'est plus nécessaire d'utiliser des variables globales. Ce concept est appelé "Closure". Exemple :
sListeElément est une chaîne sSéparateur est une chaîne = RC ArbreListeFils(ARBRE_ChampArbre, "", MaProcédureInterne)  PROCÉDURE INTERNE MaProcédureInterne(NomArbre, Branche) sListeElément += [sSéparateur] + Branche FIN
Imbrication de procédures internes Les procédures internes peuvent être imbriquées. Chaque procédure interne peut accéder aux variables des procédures qui l'incluent. Exemple :
VariableExterne est un entier Trace(VariableExterne) MaProcédureInterne1() PROCÉDURE INTERNE MaProcédureInterne1() VariableInterne1 est un entier Trace(VariableExterne + VariableInterne1) MaProcédureInterne2() PROCÉDURE INTERNE MaProcédureInterne2() VariableInterne2 est un entier Trace(VariableExterne + VariableInterne1 + VariableInterne2) FIN FIN
Procédures internes soeurs Deux procédures internes présentes dans la même procédure peuvent s'appeler entre elles (procédures internes soeurs). Exemple :
PROCÉDURE INTERNE MaProcédurePrincipale()  PROCÉDURE INTERNE MaProcédureInterne1() ... FIN  PROCÉDURE INTERNE MaProcédureInterne2() ... // Appel de la procédure soeur MaProcédureInterne1() FIN FIN
Appels récursifs Une procédure interne peut s'appeler elle-même de façon récursive. Paramètres nommés Si une procédure interne possède des paramètres avec des valeurs par défaut, il est possible d'appeler la procédure interne en nommant ses paramètres. Deux syntaxes sont possibles : - Paramètres nommés monolignes,
- Paramètres nommés multilignes.
Compilation dynamique Il est possible d'utiliser une procédure interne dans un code compilé dynamiquement (avec la fonction Compile par exemple). Exemple :
lsCode est chaîne = [ // Code compilé dynamiquement sListeElément est une chaîne sSéparateur est une chaîne = RC ArbreListeFils(ARBRE_ChampArbre, "", MaProcédureInterne)  PROCEDURE INTERNE MaProcédureInterne(NomArbre, Branche) sListeElément += [sSéparateur] + Branche FIN  ]  lsRésultat est chaîne  lsRésultat = Compile("MaProc",lsCode)
Procédure interne et attributs d'extension Les attributs d'extensions peuvent être utilisés avec les procédures internes. Par exemple, un traitement unique peut exécuter une procédure interne dans un thread secondaire pour ne pas être bloquant, puis appeler une seconde procédure dans le thread principal pour mettre à jour l'interface. Exemple :
// Code d'un bouton par exemple ... ExécutionAsynchrone()  PROCÉDURE INTERNE ExécutionAsynchrone() <thread>  // Ici exécution d'un traitement en tâche de fond // dans un thread secondaire (pas d'accès à l'interface) ThreadPause(5s)  // Traitement terminé, rappel d'un traitement du thread principal // donc autorisé à mettre à jour l'interface AprèsExécutionAsynchrone() FIN  PROCÉDURE INTERNE AprèsExécutionAsynchrone() <thread principal> Trace("Terminé ...") FIN
Cas particulier : Utilisation de procédures internes avec des fonctions asynchrones Les procédures internes peuvent être utilisées comme "Callback" pour des fonctions asynchrones. ATTENTION : Dans ce cas, le code situé après l'appel de la fonction utilisant une procédure WLangage asynchrone sera exécuté AVANT le code de la procédure Interne. Exemple : Dans cet exemple pour WINDEV Mobile, le code situé après la fonction AlbumSélecteur sera exécuté AVANT la procédure interne. La procédure interne sera appelée lorsque l'utilisateur aura validé le sélecteur.
AlbumSélecteur(albumImage, SélectionPhoto) PROCÉDURE INTERNE SélectionPhoto(sCheminImage) IMG_ChampImage = sCheminImage FIN // Code exécuté après la fonction AlbumSélecteur mais // AVANT le code de la procédure interne.
- Une procédure interne ne peut pas avoir le même nom que la ou les procédures qui la contiennent.
- Deux procédures internes de même niveau ne peuvent pas avoir le même nom, même si elles sont déclarées dans des blocs de code différents (SI ALORS SINON, ...).
- Les procédures internes ne sont pas disponibles en compilation dynamique.
- Il n'est pas possible d'automatiser l'exécution d'une procédure interne.
- La gestion automatique des erreurs n'est pas disponible sur les procédures internes.
- Si l'option "Portée des variables locales limitée au bloc courant" est activée dans l'onglet "Compilation" de la description du projet, la déclaration de procédures internes utilisant des variables "avec limitation de portée" entraînera une erreur de génération. Exemple :
- le code suivant provoque une erreur de compilation :
PROCÉDURE MaProcedure()
SI MaCondition ALORS
str est une chaîne
PROCÉDURE INTERNE ma_proc_interne()
str = "truc"
FIN
FIN
- Pour corriger ce code, il est nécessaire de ne pas déclarer la variable dans l'instruction SI :
PROCÉDURE MaProcedure()
str est une chaîne
SI MaCondition ALORS
PROCÉDURE INTERNE ma_proc_interne()
str = "truc"
FIN
FIN
En Java et Android, il est recommandé de toujours déclarer les procédures internes dans la portée de la procédure elle-même. Ainsi, si des variables non déclarées sont utilisées, des erreurs de compilation seront affichées.
Documentation également disponible pour…
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|