Introduction au Lua/Erreurs
Après avoir abordé la structure particulière des modules Scribunto pour Mediawiki, nous avons ensuite étudié quelques caractéristiques élémentaires du langage Lua (ses variables, ses expressions) d'autres caractéristiques fondamentales comme les conditions, les boucles ou encore les fonctions. Nous avons vu ensuite comment la manipulation des tables avec Lua est à la fois essentielle et particulière. Cette nouvelle leçon montre comment gérer les erreurs et exceptions au sein d'un script en cours d’exécution[1].
Prérequis
[modifier | modifier le wikicode]Cette leçon suppose que vous ayez assimilé la leçon Tables.
Créer un script Lua avec un système de gestion des exceptions
[modifier | modifier le wikicode]- Accéder au Module:Sandbox.
- Supprimer le code existant.
- Ajouter le code suivant et enregistrer la page:
local p = {}
local function reciprocal1(value)
return 1 / value
end
function p.test1(frame)
local value = frame.args[1]
return reciprocal1(value)
end
local function reciprocal2(value)
if value == nil then
error('value must exist')
end
if tonumber(value) == nil then
error('value must be a number')
end
if tonumber(value) == 0 then
error('value must not be 0')
end
return 1 / value
end
function p.test2(frame)
local value = frame.args[1]
return reciprocal2(value)
end
local function reciprocal3(value)
assert(value, 'value must exist')
assert(tonumber(value), 'value must be a number')
assert(tonumber(value) ~= 0, 'value must not be zero')
return 1 / value
end
function p.test3(frame)
local value = frame.args[1]
return reciprocal3(value)
end
function p.test4(frame)
local value = frame.args[1]
if pcall(function () result = reciprocal3(value) end) then
return result
else
return 'Error: Value must exist, must be numeric, and not zero.'
end
end
return p
Tester votre nouveau script
[modifier | modifier le wikicode]- Rendez-vous sur "votre page de test".
- Ajouter le code suivant et enregistrer la page:
;Reciprocal 1 :{{#invoke:Sandbox|test1}} :{{#invoke:Sandbox|test1|x}} :{{#invoke:Sandbox|test1|0}} :{{#invoke:Sandbox|test1|2}} ;Reciprocal 2 :{{#invoke:Sandbox|test2}} :{{#invoke:Sandbox|test2|x}} :{{#invoke:Sandbox|test2|0}} :{{#invoke:Sandbox|test2|2}} ;Reciprocal 3 :{{#invoke:Sandbox|test3}} :{{#invoke:Sandbox|test3|x}} :{{#invoke:Sandbox|test3|0}} :{{#invoke:Sandbox|test3|2}} ;Reciprocal 4 :{{#invoke:Sandbox|test4}} :{{#invoke:Sandbox|test4|x}} :{{#invoke:Sandbox|test4|0}} :{{#invoke:Sandbox|test4|2}}
Le résultat doit correspondre à ceci:
;Reciprocal 1
'Erreur Lua dans Module:Sandbox à la ligne 4 : attempt to perform arithmetic on local 'value' (a nil value).'
'Erreur Lua dans Module:Sandbox à la ligne 4 : attempt to perform arithmetic on local 'value' (a string value).'
inf
0.5
;Reciprocal 2
'Erreur Lua dans Module:Sandbox à la ligne 14 : value must exist.'
'Erreur Lua dans Module:Sandbox à la ligne 17 : value must be a number.'
'Erreur Lua dans Module:Sandbox à la ligne 20 : value must not be 0.'
0.5
;Reciprocal 3
'Erreur Lua dans Module:Sandbox à la ligne 31 : value must exist.'
'Erreur Lua dans Module:Sandbox à la ligne 32 : value must be a number.'
'Erreur Lua dans Module:Sandbox à la ligne 33 : value must not be zero.'
0.5
;Reciprocal 4
'Error: Value must exist, must be numeric, and not zero.'
'Error: Value must exist, must be numeric, and not zero.'
'Error: Value must exist, must be numeric, and not zero.'
0.5
Comprendre le nouveau script
[modifier | modifier le wikicode]Comprendre la fonction reciprocal1
[modifier | modifier le wikicode]local function reciprocal1(value)
déclare une fonction locale nomméereciprocal1
qui accepte un unique paramètrevalue
, qui est la valeur dont l'inverse sera retourné.return 1 / value
retourne l'inverse de la valeur.end
termine la fonction.
Comprendre la fonction test1
[modifier | modifier le wikicode]function p.test1(frame)
déclare une fonction locale nomméetest1
qui accepte un unique paramètreframe
, qui est l'objet utile pour accéder aux paramètres passés par #invoke.local value = frame.args[1]
définit une variable locale nomméevalue
et lui assigne la valeur du premier argument (paramètre) de l’objet "frame" passé par #invoke.return reciprocal1(value)
appel la fonctionreciprocal1
, en lui passant la variablevalue
et retourne le résultat.end
termine la fonction.
Comprendre la fonction reciprocal2
[modifier | modifier le wikicode]local function reciprocal2(value)
déclare une fonction locale nomméereciprocal2
qui accepte un unique paramètrevalue
, qui est la valeur dont l'inverse sera retourné.if value == nil then
créé un bloc conditionnel et test si la variablevalue
est de typenil
. Dans l'affirmative une erreur est générée.error('value must exist')
génère une erreur avec la chaîne de caractère littérale comme message d'erreur (error statement). L'utilisation de la fonctionerror()
permet au programmeur de choisir le texte du message d'erreur qui sera retourné à la fonction ou à la page qui a invoqué la fonction.- Lorsqu'une erreur est générée, l’exécution retourne immédiatement à la fonction appelante. Aucune instruction dans cette même fonction venant après l'erreur ne sera traitée.
- ...
if tonumber(value) == nil
créé un bloc conditionnel et test si la variablevalue
est de type numérique. Dans la négative le code,tonumber
retournenil
et une erreur est générée. (convertit en numerique et évalue si le résultat vaut zéro)... if tonumber(value) == 0
créé un bloc conditionnel et test si la variablevalue
vaut0
. Dans l'affirmative une erreur est générée.return 1 / value
retourne l'inverse de la valeur.end
termine la fonction.
Comprendre la fonction test2
[modifier | modifier le wikicode]function p.test2(frame)
et le code qui suit, déclare une fonction locale nomméetest2
qui accepte un unique paramètreframe
, qui est l'objet utile pour accéder aux paramètres passés par #invoke.local value = frame.args[1]
définit une variable locale nomméevalue
et lui assigne la valeur du premier argument (paramètre) de l’objet "frame" passé par #invoke.return reciprocal2(value)
appel la fonctionreciprocal2
, en lui passant la variablevalue
et retourne le résultat.end
termine la fonction.
Comprendre la fonction reciprocal3
[modifier | modifier le wikicode]local function reciprocal3(value)
déclare une fonction locale nomméereciprocal3
qui accepte un unique paramètrevalue
, qui est la valeur dont l'inverse sera retourné.- ...
assert(value, 'value must exist')
créé une condition interne qui test si la variablevalue
est de typenil
Dans l'affirmative une erreur est générée...- L'usage de
assert
fait partie des meilleures pratiques pour documenter et tester les postulats sur les variables passées en paramètres.
- L'usage de
assert(tonumber(value), 'value must be a number')
créé une condition interne qui test si la variablevalue
est de type numérique. Dans la négative,tonumber
retournenil
, une erreur est générée.assert(tonumber(value) ~= 0, 'value must not be zero')
créé une condition interne qui test si la variablevalue
vaut0
. Dans l'affirmative une erreur est générée.return 1 / value
retourne l'inverse de la valeur.end
termine la fonction.
Comprendre la fonction test3
[modifier | modifier le wikicode]function p.test3(frame)
et le code qui suit, déclare une fonction locale nomméetest3
qui accepte un unique paramètreframe
, qui est l'objet utile pour accéder aux paramètres passés par #invoke.local value = frame.args[1]
définit une variable locale nomméevalue
et lui assigne la valeur du premier argument (paramètre) de l’objet "frame" passé par #invoke.return reciprocal3(value)
appel la fonctionreciprocal3
, en lui passant la variablevalue
et retourne le résultat.end
termine la fonction.
Comprendre la fonction test4
[modifier | modifier le wikicode]function p.test4(frame)
et le code qui suit, déclare une fonction locale nomméetest4
qui accepte un unique paramètreframe
, qui est l'objet utile pour accéder aux paramètres passés par #invoke.local value = frame.args[1]
définit une variable locale nomméevalue
et lui assigne la valeur du premier argument (paramètre) de l’objet "frame" passé par #invoke.if pcall(function () result = reciprocal3(value) end) then
créé une condition interne qui appel la fonctionreciprocal3
, lui passe la variablevalue
et stocke le résultat. Si aucune erreur ne se produit, la variableresult
est retournée. Si une erreur se produit, une chaine de caractère est renvoyé comme message d'erreur.pcall()
utilise la fonction prédéfinie pcall (protected call) pour appeler une seconde fonction et intercepter les erreurs qui ont lieu.function () ... end
créé une fonction interne anonyme qui exécute le code dans ... comme un appel de fonction.- La fonction anonyme est nécessaire pour enregistrer le resultat de la fonction
reciprocal3
alors que la fonctionpcall()
sert à intercepter n'importe quelle erreur qui se produit.
- La fonction anonyme est nécessaire pour enregistrer le resultat de la fonction
end
termine la fonction.
Conclusion
[modifier | modifier le wikicode]Félicitation! Vous êtes capable de créer, tester et comprendre un script Lua qui contient un système de gestion des erreurs et exceptions. Continuez avec la leçon suivante Fonctions mathématiques ou choisissez l'étude d'une autre bibliothèque Lua ou Scribunto dans la barre verticale.
Voir aussi
[modifier | modifier le wikicode]- Initiation au Lua avec Scribunto/Débogage
- Wikipedia: Système de gestion d'exceptions
- Wikipedia: Assertion
Références
[modifier | modifier le wikicode]- ↑ http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manualfr#Gestion_des_erreurs Manuel de référence Lua, Gestion des erreurs