Logo Spiria

Apprendre Lua pour les développeurs Python

2 mai 2016.

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 :

 

[Photo Technodwarf.]