Retour au cours

games / lua

Bases : variables, types et opérateurs

Leçon 11 exercice

Explication

Un peu d'histoire

Lua est créé en 1993 au Brésil, par Roberto Ierusalimschy, Luiz Henrique de Figueiredo et Waldemar Celes, à l'université PUC-Rio de Rio de Janeiro. "Lua" signifie tout simplement "lune" en portugais. Dès sa conception, le langage est pensé pour être léger, rapide et surtout facile à intégrer ("embarquer") dans une application déjà écrite en C — plutôt qu'un langage autonome destiné à tourner seul.

Pourquoi apprendre Lua aujourd'hui

Lua est extrêmement présent dans le monde du jeu vidéo comme langage de script : World of Warcraft, Roblox, ou encore les serveurs de jeu FiveM l'utilisent pour permettre aux joueurs et créateurs de personnaliser le comportement du jeu sans toucher au moteur écrit en C/C++. On le retrouve aussi dans des outils bien connus comme l'éditeur Neovim ou la base de données Redis. Sa légèreté et sa facilité d'intégration en font le langage de choix chaque fois qu'une application doit devenir "scriptable" par ses utilisateurs.

Ce que vous allez apprendre

  • Déclarer une variable locale et comprendre pourquoi c'est presque toujours le bon choix
  • Distinguer les types fondamentaux de Lua (nil, boolean, number, string, table, function)
  • Reconnaître la distinction integer/float à l'intérieur du type number (Lua 5.3+)
  • Appliquer la règle du "truthy/falsy" propre à Lua, différente de la plupart des autres langages
  • Utiliser les bons opérateurs Lua (.. pour concaténer, ~= pour "différent de") sans les confondre avec d'autres langages

Dans quel contexte ?

Imagine un créateur de contenu qui script sa toute première interaction sur un serveur FiveM : afficher le nom du joueur, son niveau et un statut "en ligne/hors ligne" dans la console. Rien de complexe en apparence, mais chaque variable posée ici pose déjà une question de portée (doit-elle être visible d'un autre script ?) et de type (un niveau est-il vraiment un texte ou un nombre ?). Ces choix, pris dès les toutes premières lignes de code, déterminent si le script restera lisible et sans bug une fois qu'il grossira.

Variables et portée : la première décision qui compte

Une variable Lua est globale par défaut si l'on oublie le mot-clé local — c'est un choix de conception historique qui surprend souvent les débutants venant d'autres langages. Une variable globale est visible partout dans le programme, ce qui semble pratique au début mais devient vite une source de bugs difficiles à tracer : deux parties du code peuvent se marcher dessus sans le savoir. Prendre l'habitude d'écrire local systématiquement, dès cette première leçon, évite ce piège pour tout le reste du cours.

Prérequis

Aucune connaissance préalable n'est nécessaire : cette leçon suppose seulement que tu sais ouvrir un fichier .lua et l'exécuter (par exemple avec lua monscript.lua en ligne de commande, ou via un serveur FiveM en développement).

Un système de types minimaliste mais avec des subtilités

Lua n'a que quelques types de base (nil, boolean, number, string, table, function...), ce qui le rend simple à apprendre. Mais deux subtilités méritent une attention particulière : la distinction interne integer/float dans le type number, et la règle du "truthy/falsy" — contrairement à beaucoup de langages où 0 ou une chaîne vide sont considérés comme faux, en Lua SEULS nil et false sont faux. Tout le reste, y compris 0, est vrai dans un test conditionnel.

Type LuaExemple de valeurFalsy ?
nilnilOui
booleantrue / falsefalse seulement
number42, 3.14Non, même 0
string"texte"Non, même ""
table{1, 2, 3}Non
functionprintNon

Piège fréquent

Venant de JavaScript ou Python, on s'attend souvent à ce que 0 ou "" soient "faux" dans un if. En Lua, ce n'est jamais le cas : seuls nil et false déclenchent la branche else. Un test comme if userInput then sur une chaîne vide "" s'exécutera donc toujours comme si une vraie valeur était présente.

Le point de départ de tout le cours

Cette leçon pose le vocabulaire de base (variables, types, opérateurs) sur lequel s'appuient toutes les suivantes — en particulier la notion de portée locale, qui redeviendra centrale dès la leçon sur les fonctions et les closures.

Commandes & code

Bases : variables, types et opérateurs

lua
-- Déclaration de variable : locale (recommandée) ou globale (à éviter, pollue l'espace global)
local playerName = "Alice"     -- string
local playerLevel = 12          -- number (Lua ne distingue pas int/float par défaut avant 5.3)
local isOnline = true            -- boolean
local inventory = nil              -- nil = absence de valeur

globalScore = 100   -- variable globale : visible partout, source classique de bugs, à éviter
lua
-- Lua 5.3+ distingue les entiers (integer) et les flottants (float) sous le type "number"
print(math.type(10))     -- "integer"
print(math.type(10.0))   -- "float"
print(math.type(10 / 2)) -- "float" : la division "/" retourne TOUJOURS un float
print(math.type(10 // 3))-- "integer" : "//" est la division entière (floor division)
lua
-- Les 8 types fondamentaux de Lua
print(type("texte"))       -- "string"
print(type(42))            -- "number"
print(type(true))          -- "boolean"
print(type(nil))           -- "nil"
print(type({}))            -- "table"
print(type(print))         -- "function"
print(type(coroutine.create(function() end))) -- "thread"
-- "userdata" : type représentant des données C opaques (utilisé côté moteur hôte, voir dernière leçon)
lua
-- Opérateurs arithmétiques
print(7 + 3, 7 - 3, 7 * 3, 7 / 3, 7 // 3, 7 % 3, 7 ^ 2)
-- 10  4  21  2.3333333333333  2  1  49.0   ("^" = puissance, retourne toujours un float)

-- Opérateurs relationnels et logiques
print(5 == 5, 5 ~= 3, 5 < 10)     -- "~=" est l'opérateur "différent de" en Lua (pas "!=")
print(true and false, true or false, not true)
lua
-- Falsy / truthy en Lua : SEULS nil et false sont "falsy", tout le reste est "truthy"
-- Piège classique venant d'autres langages : 0 et "" sont TRUTHY en Lua (contrairement à JS/Python)
if 0 then print("0 est truthy en Lua") end        -- s'affiche
if "" then print("chaîne vide est truthy") end     -- s'affiche

local x = nil
local y = x or "valeur par défaut"   -- pattern idiomatique Lua pour une valeur par défaut
print(y)  -- "valeur par défaut"
lua
-- Concaténation de chaînes avec ".." (deux points), pas "+"
local first = "Techno"
local second = "logik"
print(first .. second)          -- "Technologik"
print("Score: " .. 42)          -- concaténation implicite number -> string : "Score: 42"

-- Conversion explicite entre types
print(tostring(42))             -- "42"
print(tonumber("42") + 1)       -- 43
print(tonumber("abc"))          -- nil (échec de conversion, à toujours vérifier)
lua
-- Portée des variables locales : bloc-scopées (do...end crée un nouveau bloc)
local level = 1
do
  local level = 2   -- masque (shadow) la variable externe DANS ce bloc uniquement
  print(level)       -- 2
end
print(level)          -- 1, la variable externe n'est pas modifiée

Résumé

  • local est le mot-clé par défaut à utiliser ; les globales sont une source classique de bugs.
  • Lua distingue integer/float sous le type number depuis la version 5.3.
  • Seuls nil et false sont falsy ; 0 et "" sont truthy, contrairement à beaucoup d'autres langages.
  • La concaténation se fait avec .., la comparaison de différence avec ~=.

Exercices pratiques

1 disponible
1

Mission : traquer un bug de statut sur un serveur FiveM

Objectif : Analyser un script de statut joueur pour trouver pourquoi un statut vide s'affiche comme actif, puis corriger le code.

Contexte

Un créateur de contenu FiveM te transmet ce script qui affiche le statut d'un joueur :

lua
local playerTag = ""
local playerLevel = 10 / 2

if playerTag then
  print("Tag défini : " .. playerTag)
else
  print("Aucun tag")
end

print(math.type(playerLevel))

Il ne comprend pas pourquoi la console affiche Tag défini : (vide) alors qu'il pensait que playerTag étant une chaîne vide, la condition else s'exécuterait. Il se demande aussi pourquoi math.type(playerLevel) renvoie "float" alors qu'il a divisé deux entiers "ronds".

Résoudre l’exercice →