Apprendre Lua pour les développeurs Python

Lors d’un précédent emploi, j’ai programmé en Lua pendant 6 mois afin de créer un jeu pour téléphone mobile. Cette expérience m’a fait remarquer plusieurs similarités entre Lua et Python.
Lors d’un précédent emploi, j’ai programmé en Lua pendant 6 mois afin de créer un jeu pour téléphone mobile. Cette expérience m’a fait remarquer plusieurs similarités entre Lua et Python.
Pour faire cet article de blogue, qui est une présentation de Lua pour ceux qui connaissent déjà Python, j’ai décidé de programmer de nouveau avec Lua en créant un autre jeu et j’ai utilisé le même environnement que par le passé : Corona SDK.
Il existe une assez bonne documentation pour Lua, mais elle n’est pas aussi facile d’utilisation que celle de Python. Pour faciliter la transition, voici quelques différences entre les deux langages.
Les tables
En Python, il existe plusieurs types de structures de données : des listes, des tuples, des ensembles et des dictionnaires.
Avec Lua, il existe une seule structure de données : la table. Cette structure fait tout, mais à la base, c’est autant une liste qu’un dictionnaire. Un module en Lua est un fichier, un peu comme pour Python. La différence est qu’à la fin, le module doit retourner une table. Cette table est la représentation du module.
On voit la table dans le fichier comme une classe, on peut en effet y ajouter des données membres et des fonctions.
-- ceci est un commentaire.
local gameScene = {} -- gameScene est une table.
gameScene.score = 0
function gameScene:loadScene() ...
-- avant la fin du fichier, on doit retourner la table
return gameScene
Les tables sont très flexibles.
La façon de déclarer la fonction loadScene dans l’exemple précédent est en réalité du sucre syntaxique pour :
gameScene["loadScene"] = function() ...
On peut donc rajouter des fonctions dans une table quand bon nous semble. De plus, pour les variables, le point “.” fait référence à une entrée dans un dictionnaire.
gameScene.score = 1000
est équivalent à :
gameScene["score"] = 1000
Il peut donc y avoir des conflits si l’on ne fait pas attention.
Cet exemple montre en quelque sorte la flexibilité de Lua mais qu’il faut toutefois être organisé. Si les fonctions et données membres sont définies un peu n’importe comment, il peut être difficile de s’y retrouver avec le temps.
Lambda et closures
Un lambda en Lua n’est pas spécial, puisqu’on peut ajouter des fonctions à une table de la manière suivante :
uneTable.testfct = function() ...
Ce qui est spécial et moins intuitif, c’est le principe des closures et de leurs upvalues.
local x = 5
local uneTable = {}
uneTable.testfct = function(y)
x = x + y
end
print x
uneTable.testfct(6)
print x
Sortie :
5
11
La variable x est une upvalue de la fonction testfct.
Opérateurs manquants
Opérateur +=
À la place, il faut utiliser la version longue :
x = x + 5
Opérateur !=
Il faut le remplacer par ~= :
local scoreData = {}
if scoreData ~= nil and scoreData[“level_one”] ~= 0 then
code
end
Opérateur unaire !
À l'instar de Python, on doit utiliser le mot-clé not.
Le mot-clé Self
Self est utilisé, mais pas exactement de la même façon. En Lua, le mot self est implicite lorsqu’on utilise les deux points pour appeler une fonction, alors qu’en Python, le mot self doit être écrit dans la liste des paramètres.
uneTable.uneFonction(5, 6)
Puisque la fonction uneFonction est appelée sur la table uneTable avec le point, self sera “null (nil)” à l’intérieur de cette fonction.
uneTable:uneFonction(5, 6)
Puisque la fonction uneFonction est appelée sur la table uneTable avec le deux-points, self sera “non-null” à l’intérieur de cette fonction et sera la représentation de la table uneTable.
Il existe des façons avancées qui permettent de modifier le comportement des tables, mais cela dépasse le cadre de cet article introductif.
Fonction et expression logique (Control Statements)
Contrairement à Python, Lua n’a pas besoin d’une indentation particulière. Les fonctions sont écrites comme ceci :
function gameScene:enter()
code
end
Même chose pour les expressions logiques :
if x > 6 then
code
else
code
end
for elem : elemTable do
code
end
Import remplacé par Require
Require est le mot utilisé pour référencer des modules à partir d’un autre module.
Dans la section sur les tables, j’ai expliqué qu’un module devait retourner sa table à la fin. En voici un exemple :
==== Dans le fichier gameScene.lua =====
local gameScene = {}
function gameScene:enter()
end
function gameScene:exit()
end
return gameScene
==== Fin fichier gameScene.lua =====
==== Dans le fichier mainMenu.lua ====
local gameScene = require "gameScene"
gameScene:exit()
==== Fin ====
Les points à noter :
- Les fonctions finissent par end ;
- require n’a pas besoin de l’extension du fichier Lua. Les fichiers référençables ont tous cette extension ;
- require ne prend pas de parenthèses, comme import en Python.
Coercition
Le système est implicite en Lua alors qu’en Python, on doit utiliser la fonction str pour passer d’un entier à une chaine de caractères.
Liens utiles
Pour continuer l’apprentissage :
- Lua Reference Manuals : http://www.lua.org/manual/.
- La première version du livre Programming in Lua est gratuite et disponible en ligne. La dernière version est payante (environ 45 CAD, version papier).
- Des tutoriels Lua très pratiques : http://lua-users.org/wiki/LuaTutorial.
- Un éditeur gratuit, Eclipse LDT, anciennement Koneki : https://eclipse.org/ldt/.
[Photo Technodwarf.]