Sommaire

1. Bases du langage

1.1 Description

Lua, lune en portugais, est un langage de script, gratuit, concis et simple :

  • Concis car le langage est assez petit aussi bien dans son nombre de mots-clés que les concepts qu'il met en jeu. Il n'y a par exemple qu'un type de données structurées, les tables, alors que de Python utilisent des tuples, des sets, des listes, des dictionnaires. L'orientation objet n'est pas supportée par des mots-clés dans le langage, il faut la reprogrammer à la main mais Lua offre des facilités pour développer les capacités du langage.
  • Simple car Lua a une syntaxe assez standard et très permissive : on peut appeler une fonction sans respecter le nombre de paramètres demandés, on peut simplement concaténer deux expressions à la suite, il n'y pas de système de typage des variables.

La version actuelle (janvier 2022) est la version 5.4 disponible selon les termes de la licence MIT. Ses fichiers portent l'extension .lua.

1.2 Historique et influences

Lua a été développé au Brésil à partir de 1993 par Roberto Ierusalimschy, Waldemar Celes et Luiz Henrique de Figueiredo au sein du groupe de recherche Computer Graphics Technology Group (TeCGraf [pt, en]), de l'université pontificale catholique de Rio de Janeiro avec l'aide du géant industriel Petrobras [en].

Sa syntaxe emprunte au langage Modula, un langage développé dans les années 70 en Suisse par Niklaus Wirth, le créateur de Pascal. Elle présente également des similarités avec le langage de script Ruby mais sans sa partie orientée objet.

1.3 Désavantages

  • Absence de mécanisme d'orientation objet de base,
  • Danger de pouvoir concaténer deux expressions à la suite, car il n'y a ni séparateur, ni terminateur : 3+5 2 est valide en Lua !
  • Une bibliothèque standard minimaliste où il manque beaucoup de choses mais de taille réduite
  • Il n'y a pas de mot clé continue pour avancer une boucle d'une itération
  • in ne s'utilise qu'avec les fonctions pairs ou ipairs dans un for
  • Opérateur de différence est ~= au lieu du standard de facto !=
  • Opérateur de puissance est ^ au lieu de **
  • Pas d'opérateurs combinés : += -= *= /=
  • Aucune vérification du nombre de paramètres des fonctions
  • Aucune déclaration de type possible
  • Fusion des types int et float en number
  • Fusion du concept de liste et de dictionnaire en celui de table
  • Difficulté à connaître la longueur d'une liste et à s'assurer de la continuité de ses index
  • On ne peut pas différencier une clé existante avec sa valeur à nil d'une clé qui n'existe pas
  • Les clés de type string doivent être entourées de crochets { ['key'] = val }
  • Aucun moyen de déclarer des constantes : Depuis Lua ⩾ 5.4 on peut avec une syntaxe horrible : local stone <const> = 42
  • Toute variable sans local est globale même dans les fonctions
  • Conversion automatique des chaînes en nombres

1.4 Utilisations

Lua peut être utilisé de deux façons :

  • Via l'interpréteur en tant qu'API C embarqué dans une application hôte. il permet de piloter celle-ci via des scripts en utilisant les fonctions supplémentaires qu'elle met à leur disposition et les bibliothèques Lua. Sa concision fait qu'il ne prend pas trop de place dans l'application hôte. On parle alors de langage d'extension (extension language) ou embarqué (embedded).
  • Via l'interpréteur en tant qu'application, appelé lua, on ne peut alors utiliser que les bibliothèques en Lua mais celles-ci sont nombreuses. On parle alors d'utilisation en tant que langage principal (stand alone). On peut utiliser ce dernier pour exécuter d'un coup des scripts Lua ou en mode interactif via une boucle REPL (read-eval-print-loop) en entrant au fur et à mesure des instructions qui sont exécutées au fur et à mesure qu'elles sont entrées dans l'interpréteur. L'interpréteur est programmé en C.

L'interpréteur n'interprète pas directement le script mais le compile en bytecode et envoi celui-ci à la machine virtuelle Lua.

Lua est utilisée de façon embarquée dans de nombreux applications, en particulier des jeux vidéo. On peut citer le lecteur multimédia VLC et le jeu vidéo World of Warcraft.

1.5 Premiers pas

La tradition veut que l'on commence par écrire "Bonjour le monde !" sur la sortie standard (console) lorsque l'on découvre un nouveau langage de programmation.

-- Ceci est un commentaire jusqu'à la fin de la ligne
print("Bonjour le monde !")

1.6 Mots réservés (22)

and   break do    else  elseif end false for    function
goto  if    in    local nil    not or    repeat return
then  true  until while

1.7 Commentaires

Commentaires en Lua :

-- mon commentaire jusqu'à la fin de la ligne

Commentaires sur plusieurs lignes :

--[[
    vos lignes
--]]

1.8 Variables

Une variable est une référence vers une valeur. Une valeur a un type, pas la variable. L'exemple suivant établie une référence entre la variable a et la valeur 5 de type number.

a = 5

Il n'y a pas de constantes en Lua : une variable peut référencer ensuite une autre valeur, du même type ou d'un autre.

Une variable peut être déclarée constante avec l'attribut const :

local stone <const> = 42

2. Types de base (8)

En Lua, il y a 8 types de base.

2.1 nil

Le type nil n'a qu'une seule valeur, nil.

2.2 Booléens : boolean

Le type boolean a deux valeurs, true et false.

Les valeurs nil et false sont les deux seules valeurs qui sont considérées comme fausse par les tests. Toutes les autres valeurs, y compris 0 et la chaîne vide "" sont vraies.

2.3 Nombres : number

Le type number a pour valeurs les entiers et les réels (ou flottants). Les conversions de l'un vers l'autre type sont automatiques. Par défaut, entiers et réels sont stockés sur 64 bits et selon la norme IEEE 754 pour les réels.

2.4 Chaînes de caractères : string

Le type string unifie les caractères et les chaînes de caractères. Lua peut stocker les chaînes en UTF-8 mais ne sait pas comment les gérer.

Les chaînes sont immutables en Lua.

2.5 Fonctions : function

Le type function sera plus étudié dans le chapitre suivant. Il s'agit de bloc de code écrit en Lua ou en C.

2.6 Données utilisateurs : userdata

Le type userdata permet de stocker des données binaires venant du code C avec lequel lua s'interface.

2.7 Processus légers : thread

Lua utilise le type thread pour ses coroutines. Ce type est indépendant des threads du système d'exploitation.

2.8 Tables : table

Lua a fusionné les listes et les tables associatives (ou dictionnaires) dans le type table : une clé désigne une valeur.

Une clé ne peut avoir pour valeur nil ou NaN.

t = { ["k1"] = 5, ["k2"] = "v", [4] = 6 } -- Définition
print(t["k1"]) -- Accès
print(t.k1) -- Accès avec sucre syntaxique

3. Opérateurs

3.1 Liste des opérateurs

Opérateurs arithmétiques

  • + addition
  • - binaire soustraction
  • * multiplication
  • / division (converti en float)
  • // division entière
  • % modulo
  • ^ puissance (converti en float)
  • - unaire signe négatif

Opérateurs de comparaisons

  • == égalité
  • ~= inégalité
  • < inférieur à
  • > supérieur à
  • <= inférieur ou égal à
  • >= supérieur ou égal à

Si les types sont différents, l'égalité renverra toujours false.

Opérateurs booléens

  • & et
  • | ou
  • ~ binaire ou exclusif
  • >> décalage à droite (rempli avec des zéros)
  • << décalage à gauche (rempli avec des zéros)
  • ~ unaire non

Opérateurs logiques

  • or ou
  • and et
  • not unaire non

Tout est faux en Lua sauf false et nil.

Opérateur Opé 1 Opé 2 Retour
and false, nil non évaluée opé 1
and autre évaluée opé 2
or autre non évaluée opé 1
or false, nil évaluée opé 2

Les opérateurs n'évaluent la deuxième opérande que si nécessaire.

Autres opérateurs

  • .. concaténation avec conversion
  • # longueur des chaînes ou bordure des tables

Attention : une table peut avoir des trous, dans ce cas la bordure n'indique pas la longueur de la table.

3.2 Précédence des opérateurs

Niveau Opérateur
1 ^
2 unaires : not # - ~
3 * / // %
4 + -
5 ..
6 << >>
7 &
8 ~
9 |
10 < > <= >= ~= ==
11 and
12 or

4. Contrôle du flux

4.1 Séquence

En Lua, le symbole pour terminer les instructions est ; mais il est totalement optionnel. Ce code est donc valide : a = 5 b = 6

4.2 Conditions

Pour qu'une partie du code ne soit exécutée que si une condition est vrai, on utilisera if :

if condition then
    actions
[ elseif condition then
    actions ] *
[ else
    actions ] ?
end

Sont considérées fausses les valeurs false et nil. Toutes les autres valeurs sont vraies (dont {} "" 0).

4.3 Répétitions

Boucle qui s'exécute tant que la condition est vraie avec while :

while condition do
    actions
end

Le corps de la boucle (ses actions) sera exécuté entre 0 et n fois.

Avec repeat, le corps de la boucle sera exécuté au moins une fois car la condition est testée après :

repeat
    actions
until condition

Autre grand classique des boucles, for qui peut-être utilisé avec un intervalle numérique :

for identifiant = debut, fin [ , pas ] do
    actions
end

Par défaut le pas est égal à 1 (si fin < début, la boucle ne s'exécutera pas une seule fois).

Ou avec une table indexée par des nombres :

for indice, valeur in ipairs(table) do
    actions
end

Ou avec une table indexée par des chaînes :

for cle, valeur in pairs(table) do
    actions
end

Dans les trois cas, on peut utiliser le mot-clé break pour sortir de la boucle.

Il n'y a pas de mot-clé continue ou next en Lua pour passer à l'itération suivante.

5. Fonctions

5.1 Définition

function id ( parametres )
    corps
end

Il s'agit d'un sucre syntaxique pour :

id = function ( parametres )
    corps
end

Les paramètres sont séparés par des virgules.

Le paramètre spécial ... indique qu'il y a des paramètres supplémentaires. Ils seront accessibles dans la variable ....

Le mot-clé return permet de retourner une expression.

5.2 Appel

Pour appeler une fonction on utilise f(p1, p2, p3).

On peut omettre les parenthèses si il y a un argument de type string ou table.

5.3 Closure

6. Gestion des exceptions et multifichiers

Il n'y a pas à proprement parler d'exception en Lua. On peut toutefois faire des appels protégés pour gérer les erreurs.

6.1 Appels protégés

6.2 Multifichiers

Pour appeler du code lua écrit dans un autre fichier, il faut faire dans le fichier appelant :

local id = require(string)

La string doit correspondr au nom du fichier sans le .lua.

7. Bibliothèque de base

7.1 Sortie et entrée console

print("Hello World!")

7.2 Nombres

7.3 Chaînes de caractères

Avoir le premier caractère d'une chaîne s : string.sub(s, 1, 1)

Pour tester si une chaîne est un nombre, on essaye de le convertir avec : tonumber(n). Si on veut tester si une chaine est un entier, on essaye de la convertir avec : tonumber(n ,base) (lua ⩾5.2). Dans les deux cas, la fonction renverra nil si elle ne peut pas.

print(tonumber("2.4")) -- retourne 2.4
print(tonumber("2.4", 10)) -- retourne nil
print(tonumber("2", 10)) --retourne 2

7.4 Tables

Pour savoir si une table contient une valeur, il faut la parcourir (!) avec un for :

a = {1,2,3,4,5,6}
searched = 3
for index, value in ipairs(a) do
  if value == searched then
    print("found", searched, "at", index)
    break
  end
end

Contient : il faut parcourir avec un for index, value in ipairs(tab) et faire value ⩵ searched

7.5 Fichiers

8. Recettes

8.1 Programmation orientée objet (POO)

8.1.1 Définir un type

local Type = {}
function Type:new()
    return setmetatable({}, {__index = Type})
end
function Type:method(params)
    cod
end

8.1.2 Instancier et appeler une méthode

local t = Type.new()
t.method(t, param)
t:method(param)

Le double point : est un sucre syntaxique pour éviter de passer en premier paramètre l'instance.

8.2 Recettes pour LÖVE

8.2.1 Afficher la console

  1. Faire un fichier conf.lua dans le répertoire du jeu
  2. Faire une fonction love.conf(t)
  3. Faire dans le corps de la fonction t.console = true

8.2.2 Faire une fonction principale

  1. Faire un fichier main.lua dans le répertoire du jeu. Love ne lance qu’un répertoire ou un fichier packagé .love
  2. Faire une fonction love.load()
  3. Mettre le code dedans dont love.window.setTitle(string)

9. Liens web

9.1 Généraux

9.2 Bibliothèques

  • LuaRocks, gestionnaire de bibliothèques
  • Penlight, une librairie fondamentale
  • LPEG pour du parsing
  • IUP pour les interfaces graphiques

9.3 Interpréteurs

9.4 Langages liés

  • Teal surlangage avec des types.
  • MoonScript un langage qui transpile en Lua.
  • Titan un langage statically-typed, ahead-of-time compiled mais surtout abandonné
  • Pallene un langage statically typed and ahead-of-time compiled, fork de Titan
  • Terra statically-typed, compiled language with manual memory management and low-level system programming language that is embedded in and meta-programmed by the Lua programming language

9.5 Outils

Damien Gouteux Aide-mémoire Lua v0.1 2017-2024