Projet:Scribunto/Guide/Les paramètres
Introduction
modifierUn module, comme un modèle, a besoin de paramètres qu'on lui passe lorsqu'on l'appelle. Quelques modèles très simples n'ont pas de paramètres (exemple : {{Section vide ou incomplète}}) mais c'est très rare et c'est à travers les paramètres que les modèles prennent tout leur sens, à savoir pouvoir s'appliquer à de nombreuses situations différentes.
Les types de paramètres
modifierComme pour les modèles, on retrouve la gestion des paramètres dans les modules. Il y a toutefois une différence importante : il existe deux jeux de paramètres reçus par un module, ces deux jeux étant indépendants :
- le premier correspond aux paramètres passés au modèle qui appelle le module, lorsqu'on l'utilise, depuis un article typiquement. Cela correspond aux paramètres tels qu'on les connaît dans les modèles.
- le second correspond aux paramètres que le modèle lui-même passe au module (en fait à la fonction du module).
Exemple : dans un article j'ai le code suivant :
(...) {{MonModèle|mo-param1|mo-param2|mo1=toto|mo2=titi}} (...)
Le modèle MonModèle lui contient l'appel à la fonction MaFonction du module MonModule comme suit :
{{#invoke|MonModule|MaFonction|mu-p1=riri|mu-p2=fifi|mu-p1|mu-p2}}
La fonction MaFonction du module MonModule sera appelée avec deux séries de paramètres :
- ceux en provenance de l'appel au modèle :
- paramètre non nommé 1 valant "mo-param1",
- paramètre non nommé 2 valant "mo-param2",
- paramètre nommé "mo1" valant "toto",
- paramètre nommé "mo2" valant "titi",
- ceux en provenance de l'appel depuis le modèle :
- paramètre nommé "mu-p1" valant "riri",
- paramètre nommé "mu-p2" valant "fifi",
- paramètre non nommé 1 valant "mu-p1",
- paramètre non nommé 2 valant "mu-p2",
Chacun de ces jeux de paramètres a des paramètres non nommés et nommés, et ceux nommés peuvent avoir le même nom (ils sont indépendants).
La fonction appelée depuis un modèle reçoit en paramètre un objet spécifique : frame. Cet objet contient (entre autre) les éléments suivants :
frame.args
: une table contenant les paramètres passés à la fonction du module par le modèle.frame:getParent()
: une méthode permettant d'accéder aux paramètres passés au modèle ou passés à un quelconque objet ayant appelé le module (un autre module…).
Observer les deux lignes de code suivantes :
local pframe = frame:getParent()
attribue à la variable localepframe
le contenu de la table des arguments de l'objet parent.local args = pframe.args
attribue à la variable localeargs
le contenu depframe
.
On accède ainsi à une table contenant les paramètres passés au modèle (et non passés par le modèle).
Structuration et accès aux paramètres
modifierLes tables de paramètres peuvent être accédées de deux façons différentes, pour les paramètres nommés et ceux non nommés. Ici on considère qu'on a une variable args qui est une table de paramètres.
- args.foo : désigne le paramètre nommé 'foo'. On peut ainsi écrire :
local valeur = args.foo
- args["foo"] : fait exactement la même chose que ci-dessus. Cette notation est toutefois nécessaire si le paramètre contient des caractères non reconnus dans les mots-clés de Lua (les accents par exemple). Ainsi si un paramètre nommé s'appelle "légende" il n'est pas possible d'écrire
valeur = args.légende
, il faut utiliservaleur = args["légende"]
. De même si le nom du paramètre est dans une variable : si une variable p contient "légende", et qu'on veut accéder au paramètre nommé "légende". Écrireargs.p
correspond à chercher le paramètre nommé "p". Il faut écrireargs[p]
qui signifie la même chose queargs["légende"]
(dans cet exemple) et correspond donc bien au paramètre nommé "légende". - args[1] : désigne le premier paramètre non nommé (quelque soit sa position réelle : les paramètres non nommés sont numérotés à partir de 1 dans l'ordre où ils sont passés). De la même façon on a args[2], args[3]…
Note : si par erreur on passe un paramètre nommé dont le nom est un nombre cela pose problème (exemple : {{foo|1=bar}}). Si vous en voyez, corrigez-les. Considérez le résultat final comme non défini (en pratique il est traité comme un paramètre non nommé, mais non positionnel).
Important :
- en Lua une entrée qui n'existe pas vaut la valeur spéciale nil. Ainsi "args.foo" fonctionne toujours, et vaudra soit la valeur du paramètre "foo" soit la valeur nil.
- un paramètre nommé est « nettoyé » de ses espaces au début et à la fin. Un paramètre non nommé est passé tel quel, avec les (éventuels) espaces (ou tabulation ou retour à la ligne) avant et après.
- sans rapport direct avec les paramètres, mais utile : la valeur nil n'est pas acceptée par la plupart des fonctions traitant des textes, fonctions souvent utilisées − par exemple pour nettoyer les espaces avant et après. Pensez à tester la présence de nil avant de passer le paramètre à une autre fonction.
Exemple de début de fonction principale
modifierIl peut y avoir plusieurs fonctions principales, appelables par des modèles, dans un module[1].
Voici un exemple de début de fonction principale définissant des variables pour les paramètres :
function z.FonctionPrincipale(frame)
local pframe = frame:getParent() -- on recupère le parent (le modèle)
local args = pframe.args -- les paramètres passés au modèle (dans un article par exemple)
local config = frame.args -- les paramètres passés au module, par le modèle
(…)
- C'est même conseillé dans le cas de gros modules. Par exemple il est plus simple de faire un module dédié aux citations d'ouvrages − avec une fonction pour citer un article, une autre pour citer un livre, un site WEB… − plutôt que de créer autant de modules différents. Il est de plus probable que toutes ces fonctions utilisent les mêmes outils (des fonctions internes au module) pour tester, mettre en forme et générer la sortie. Cela évite donc de devoir recopier ces fonctions dans différents modules.
Notes sur la valeur nil
modifierPrincipalement dans le cas des paramètres on est souvent confronté à la valeur nil, qui indique l'absence de valeur (l'absence du paramètre). Comme cette valeur n'est pas acceptée par de nombreuses fonctions il faut y prendre garde. Les moyens de le gérer sont divers.
Test lors de l'utilisation
modifier local param = args["foo"] -- on récupère le paramètre nommé 'foo'
-- si le paramètre n'est pas vide on l'utilise
if (nil ~= param) then
result = z.traite_parametre(param)
end
Ici on vérifie que le paramètre existe. L'opérateur de comparaison est "==" pour l'égalité et "~=" pour la différence. On peut écrire nil ~= param
ou param ~= nil
, c'est identique. Dans cet exemple si le paramètre est nil on évite donc de le passer à traite_parametre()
qui pourrait avoir des problèmes sinon.
Si traite_parametre()
est appelé souvent il est plus simple en terme de code de mettre le test dans la fonction elle-même plutôt que de tester avant chaque appel la valeur du paramètre.
Test lors de la récupération
modifierOn peut aussi tester à la récupération du paramètre. En effet une variable (ou une constante) « vaut » sa valeur, et la valeur nil est fausse. Il est donc possible de tester à la volée une valeur et de la remplacer par une autre. Exemple :
local param = args["foo"] or ""
Concentrons-nous sur la partie à droite du "=" : Lua évalue args["foo"]
(ou args.foo
, c'est pareil). S'il vaut nil, il est faux. Le mot-clé or correspond au OU. Si la partie à gauche du ou est vrai (différente de nil) alors l'expression "a or b" vaut "a", sinon elle vaut "b". Donc ici la variable param vaudra args.foo
si celui-ci est différent de nil et la chaîne vide (un texte de longueur 0) sinon.
Ainsi on n'a jamais par la suite à se préoccuper du cas où l'un des paramètres contient nil.
Notez toutefois que ceci ne permet plus de distinguer ensuite le cas où le paramètre était absent (absent → nil → "") et le cas où le paramètre était vide via un appel du type {{MonModele|foo=|bar=toto}}
(vide → ""), ce qui peut être un problème si un paramètre vide est différent dans la sémantique du modèle d'un paramètre absent.