Débuter avec Lua
Commentaires
Les commentaires sur une seule ligne en Lua commencent par --
et continuent jusqu’à la fin de la ligne :
-- this is single line comment
-- need another line
-- huh?
Les commentaires de bloc commencent par --[[
et se terminent par ]]
:
--[[
This is block comment.
So, it can go on...
and on...
and on....
]]
Les commentaires de bloc utilisent le même style de délimiteurs que les chaînes longues ; n’importe quel nombre de signes égal peut être ajouté entre les parenthèses pour délimiter un commentaire :
--[=[
This is also a block comment
We can include "]]" inside this comment
--]=]
--[==[
This is also a block comment
We can include "]=]" inside this comment
--]==]
Une astuce pour commenter des morceaux de code consiste à l’entourer de --[[
et --]]
:
--[[
print'Lua is lovely'
--]]
Pour réactiver le bloc, ajoutez simplement un “-” à la séquence d’ouverture du commentaire :
---[[
print'Lua is lovely'
--]]
De cette façon, la séquence --
dans la première ligne commence un commentaire sur une seule ligne, tout comme la dernière ligne, et l’instruction print
n’est pas commentée.
Pour aller plus loin, deux blocs de code peuvent être configurés de telle sorte que si le premier bloc est commenté, le second ne le sera pas, et vice versa :
---[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Pour activer le deuxième bloc tout en désactivant le premier bloc, supprimez le “-” de début sur la première ligne :
--[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Installation
Binaires
Les binaires Lua sont fournis par la plupart des distributions GNU/Linux sous forme de paquet.
Par exemple, sur Debian, Ubuntu et leurs dérivés, il peut être acquis en exécutant ceci :
sudo apt-get install lua50
sudo apt-get install lua51
sudo apt-get install lua52
Il existe des versions semi-officielles fournies pour Windows, MacOS et d’autres systèmes d’exploitation hébergés sur [SourceForge] (http://luabinaries.sourceforge.net/).
Les utilisateurs d’Apple peuvent également installer Lua facilement en utilisant Homebrew :
brew install lua
(Actuellement, Homebrew a 5.2.4, pour 5.3 voir Homebrew/versions.)
La source
La source est disponible sur la page officielle. L’acquisition de sources et la construction elle-même devraient être triviales. Sur les systèmes Linux, ce qui suit devrait suffire :
$ wget http://lua.org/ftp/lua-5.3.3.tar.gz
$ echo "a0341bc3d1415b814cc738b2ec01ae56045d64ef ./lua-5.3.3.tar.gz" | sha1sum -c -
$ tar -xvf ./lua-5.3.3.tar.gz
$ make -C ./lua-5.3.3/ linux
Dans l’exemple ci-dessus, nous téléchargeons essentiellement une source tarball
depuis le site officiel, vérifions sa somme de contrôle, puis extrayons et exécutons make
. (Vérifiez la somme de contrôle sur [la page officielle][1].)
Remarque : vous devez spécifier la cible de génération souhaitée. Dans l’exemple, nous avons spécifié linux
. Les autres cibles de construction disponibles incluent solaris
, aix
, bsd
, freebsd
, macosx
, mingw
, etc. Consultez doc/readme.html
, qui est inclus dans la source, pour plus d’informations. détails. (Vous pouvez également trouver [la dernière version du README en ligne][1].)
Modules
Les bibliothèques standards sont limitées aux primitives :
coroutine
- fonctionnalité de gestion de la coroutinedebug
- crochets et outils de débogageio
- primitives IO de basepackage
- fonctionnalité de gestion des modulesstring
- fonction de correspondance de chaînes et de modèles spécifiques à Luatable
- primitives pour traiter un type Lua essentiel mais complexe - tablesos
- opérations de base du système d’exploitationutf8
- primitives UTF-8 de base (depuis Lua 5.3)
Toutes ces bibliothèques peuvent être désactivées pour une version spécifique ou chargées au moment de l’exécution.
Les bibliothèques et l’infrastructure Lua tierces pour la distribution de modules sont rares, mais s’améliorent. Des projets comme LuaRocks, Lua Toolbox et LuaDist améliorent la situation. De nombreuses informations et de nombreuses suggestions peuvent être trouvées sur l’ancien [Lua Wiki] (http://lua-users.org/wiki/), mais sachez que certaines de ces informations sont assez anciennes et obsolètes.
[1] : https://www.lua.org/download.html
Commencer
variables
var = 50 -- a global variable
print(var) --> 50
do
local var = 100 -- a local variable
print(var) --> 100
end
print(var) --> 50
-- The global var (50) still exists
-- The local var (100) has gone out of scope and can't be accessed any longer.
les types
num = 20 -- a number
num = 20.001 -- still a number
str = "zaldrizes buzdari iksos daor" -- a string
tab = {1, 2, 3} -- a table (these have their own category)
bool = true -- a boolean value
bool = false -- the only other boolean value
print(type(num)) --> 'number'
print(type(str)) --> 'string'
print(type(bool)) --> 'boolean'
type(type(num)) --> 'string'
-- Functions are a type too, and first-class values in Lua.
print(type(print)) --> prints 'function'
old_print = print
print = function (x) old_print "I'm ignoring the param you passed me!" end
old_print(type(print)) --> Still prints 'function' since it's still a function.
-- But we've (unhelpfully) redefined the behavior of print.
print("Hello, world!") --> prints "I'm ignoring the param you passed me!"
Le type spécial “nil”
Un autre type en Lua est “nil”. La seule valeur dans le type nil
est nil
. ’nil’ existe pour être différent de toutes les autres valeurs en Lua. C’est une sorte de valeur sans valeur.
print(foo) -- This prints nil since there's nothing stored in the variable 'foo'.
foo = 20
print(foo) -- Now this prints 20 since we've assigned 'foo' a value of 20.
-- We can also use `nil` to undefine a variable
foo = nil -- Here we set 'foo' to nil so that it can be garbage-collected.
if nil then print "nil" end --> (prints nothing)
-- Only false and nil are considered false; every other value is true.
if 0 then print "0" end --> 0
if "" then print "Empty string!" --> Empty string!
expressions
a = 3
b = a + 20 a = 2 print(b, a) -- hard to read, can also be written as
b = a + 20; a = 2; print(a, b) -- easier to read, ; are optional though
true and true --> returns true
true and 20 --> 20
false and 20 --> false
false or 20 --> 20
true or 20 --> true
tab or {}
--> returns tab if it is defined
--> returns {} if tab is undefined
-- This is useful when we don't know if a variable exists
tab = tab or {} -- tab stays unchanged if it exists; tab becomes {} if it was previously nil.
a, b = 20, 30 -- this also works
a, b = b, a -- switches values
Définition des fonctions
function name(parameter)
return parameter
end
print(name(20)) --> 20
-- see function category for more information
name = function(parameter) return parameter end -- Same as above
booléens
Seuls “false” et “nil” sont évalués comme faux, tout le reste, y compris “0” et la chaîne vide, sont évalués comme vrai.
collecte des ordures
tab = {"lots", "of", "data"}
tab = nil; collectgarbage()
-- tab does no longer exist, and doesn't take up memory anymore.
les tables
tab1 = {"a", "b", "c"}
tab2 = tab1
tab2[1] = "d"
print(tab1[1]) --> 'd' -- table values only store references.
--> assigning tables does not copy its content, only the reference.
tab2 = nil; collectgarbage()
print(tab1) --> (prints table address) -- tab1 still exists; it didn't get garbage-collected.
tab1 = nil; collectgarbage()
-- No more references. Now it should actually be gone from memory.
Ce sont les bases, mais il y a une section sur les tables avec plus d’informations.
les conditions
if (condition) then
-- do something
elseif (other_condition) then
-- do something else
else
-- do something
end
pour les boucles
Il existe deux types de boucle for
en Lua : une boucle for
numérique et une boucle for
générique.
-
Une boucle
for
numérique a la forme suivante :for a=1, 10, 2 do -- for a starting at 1, ending at 10, in steps of 2 print(a) --> 1, 3, 5, 7, 9 end
The third expression in a numeric
for
loop is the step by which the loop will increment. This makes it easy to do reverse loops:for a=10, 1, -1 do print(a) --> 10, 9, 8, 7, 6, etc. end
If the step expression is left out, Lua assumes a default step of 1.
for a=1, 10 do print(a) --> 1, 2, 3, 4, 5, etc. end
Also note that the loop variable is local to the
for
loop. It will not exist after the loop is over. -
Les boucles
for
génériques fonctionnent sur toutes les valeurs renvoyées par une fonction d’itération :for key, value in pairs({"some", "table"}) do print(key, value) --> 1 some --> 2 table end
Lua fournit plusieurs itérateurs intégrés (par exemple, pairs
, ipairs
), et les utilisateurs peuvent également définir leurs propres itérateurs personnalisés à utiliser avec des boucles for
génériques.
faire des blocs
local a = 10
do
print(a) --> 10
local a = 20
print(a) --> 20
end
print(a) --> 10
Quelques trucs délicats
Parfois, Lua ne se comporte pas comme on le penserait après avoir lu la documentation. Certains de ces cas sont :
Nil et Nothing ne sont pas pareils (PIEGE COMMUN !)
Comme prévu, table.insert(my_table, 20)
ajoute la valeur 20
à la table, et table.insert(my_table, 5, 20)
ajoute la valeur 20 à la 5ème position.
Que fait table.insert(my_table, 5, nil)
? On pourrait s’attendre à ce qu’il traite ’nil’ comme aucun argument et insère la valeur ‘5’ à la fin du tableau, mais il ajoute en fait la valeur ’nil’ à la 5e position du tableau.
Quand est-ce un problème ?
(function(tab, value, position)
table.insert(tab, position or value, position and value)
end)({}, 20)
-- This ends up calling table.insert({}, 20, nil)
-- and this doesn't do what it should (insert 20 at the end)
Une chose similaire se produit avec tostring()
:
print (tostring(nil)) -- this prints "nil"
table.insert({}, 20) -- this returns nothing
-- (not nil, but actually nothing (yes, I know, in lua those two SHOULD
-- be the same thing, but they aren't))
-- wrong:
print (tostring( table.insert({}, 20) ))
-- throws error because nothing ~= nil
--right:
local _tmp = table.insert({}, 20) -- after this _tmp contains nil
print(tostring(_tmp)) -- prints "nil" because suddenly nothing == nil
Cela peut également entraîner des erreurs lors de l’utilisation d’un code tiers. Si, par exemple, la documentation de certaines fonctions indique “retourne des beignets si chanceux, nul sinon”, l’implémentation pourrait ressembler un peu à ceci
function func(lucky)
if lucky then
return "donuts"
end
end
cette implémentation peut sembler raisonnable au premier abord ; il renvoie des beignets quand il le faut, et lorsque vous tapez result = func(false)
, le résultat contiendra la valeur nil
.
Cependant, si l’on écrivait print(tostring(func(false)))
lua lancerait une erreur qui ressemble un peu à celle-ci stdin:1: bad argument #1 to 'tostring' (valeur attendue)
Pourquoi donc? tostring
obtient clairement un argument, même s’il est nil
. Mauvais. func ne renvoie rien du tout, donc tostring(func(false))
est identique à tostring()
et NON identique à tostring(nil)
.
Les erreurs disant “valeur attendue” sont une forte indication que cela pourrait être la source du problème.
Laisser des vides dans les tableaux
C’est un énorme piège si vous débutez avec lua, et il y a beaucoup d’[informations](https://www.wikiod.com/fr/lua/les-tables#Éviter les lacunes dans les tableaux utilisés comme tableaux as-arrays#t=20170113143427074516) dans la catégorie tables
Exécuter des programmes Lua
Habituellement, Lua est livré avec deux binaires :
lua
- interpréteur autonome et shell interactifluac
- compilateur de bytecode
Disons que nous avons un exemple de programme (bottles_of_mate.lua
) comme celui-ci :
local string = require "string"
function bottle_take(bottles_available)
local count_str = "%d bottles of mate on the wall."
local take_str = "Take one down, pass it around, " .. count_str
local end_str = "Oh noes, " .. count_str
local buy_str = "Get some from the store, " .. count_str
local bottles_left = 0
if bottles_available > 0 then
print(string.format(count_str, bottles_available))
bottles_left = bottles_available - 1
print(string.format(take_str, bottles_left))
else
print(string.format(end_str, bottles_available))
bottles_left = 99
print(string.format(buy_str, bottles_left))
end
return bottles_left
end
local bottle_count = 99
while true do
bottle_count = bottle_take(bottle_count)
end
Le programme lui-même peut être exécuté en exécutant ce qui suit sur votre shell :
$ lua bottles_of_mate.lua
La sortie devrait ressembler à ceci, s’exécutant dans la boucle sans fin :
Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
98 bottles of mate on the wall.
Take one down, pass it around, 97 bottles of mate on the wall.
97 bottles of mate on the wall.
...
...
3 bottles of mate on the wall.
Take one down, pass it around, 2 bottles of mate on the wall.
2 bottles of mate on the wall.
Take one down, pass it around, 1 bottles of mate on the wall.
1 bottles of mate on the wall.
Take one down, pass it around, 0 bottles of mate on the wall.
Oh noes, 0 bottles of mate on the wall.
Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
...
Vous pouvez compiler le programme dans le bytecode de Lua en exécutant ce qui suit sur votre shell :
$ luac bottles_of_mate.lua -o bottles_of_mate.luac
La liste des bytecodes est également disponible en exécutant ce qui suit :
$ luac -l bottles_of_mate.lua
main <./bottles.lua:0,0> (13 instructions, 52 bytes at 0x101d530)
0+ params, 4 slots, 0 upvalues, 2 locals, 4 constants, 1 function
1 [1] GETGLOBAL 0 -1 ; require
2 [1] LOADK 1 -2 ; "string"
3 [1] CALL 0 2 2
4 [22] CLOSURE 1 0 ; 0x101d710
5 [22] MOVE 0 0
6 [3] SETGLOBAL 1 -3 ; bottle_take
7 [24] LOADK 1 -4 ; 99
8 [27] GETGLOBAL 2 -3 ; bottle_take
9 [27] MOVE 3 1
10 [27] CALL 2 2 2
11 [27] MOVE 1 2
12 [27] JMP -5 ; to 8
13 [28] RETURN 0 1
function <./bottles.lua:3,22> (46 instructions, 184 bytes at 0x101d710)
1 param, 10 slots, 1 upvalue, 6 locals, 9 constants, 0 functions
1 [5] LOADK 1 -1 ; "%d bottles of mate on the wall."
2 [6] LOADK 2 -2 ; "Take one down, pass it around, "
3 [6] MOVE 3 1
4 [6] CONCAT 2 2 3
5 [7] LOADK 3 -3 ; "Oh noes, "
6 [7] MOVE 4 1
7 [7] CONCAT 3 3 4
8 [8] LOADK 4 -4 ; "Get some from the store, "
9 [8] MOVE 5 1
10 [8] CONCAT 4 4 5
11 [9] LOADK 5 -5 ; 0
12 [11] EQ 1 0 -5 ; - 0
13 [11] JMP 16 ; to 30
14 [12] GETGLOBAL 6 -6 ; print
15 [12] GETUPVAL 7 0 ; string
16 [12] GETTABLE 7 7 -7 ; "format"
17 [12] MOVE 8 1
18 [12] MOVE 9 0
19 [12] CALL 7 3 0
20 [12] CALL 6 0 1
21 [13] SUB 5 0 -8 ; - 1
22 [14] GETGLOBAL 6 -6 ; print
23 [14] GETUPVAL 7 0 ; string
24 [14] GETTABLE 7 7 -7 ; "format"
25 [14] MOVE 8 2
26 [14] MOVE 9 5
27 [14] CALL 7 3 0
28 [14] CALL 6 0 1
29 [14] JMP 15 ; to 45
30 [16] GETGLOBAL 6 -6 ; print
31 [16] GETUPVAL 7 0 ; string
32 [16] GETTABLE 7 7 -7 ; "format"
33 [16] MOVE 8 3
34 [16] MOVE 9 0
35 [16] CALL 7 3 0
36 [16] CALL 6 0 1
37 [17] LOADK 5 -9 ; 99
38 [18] GETGLOBAL 6 -6 ; print
39 [18] GETUPVAL 7 0 ; string
40 [18] GETTABLE 7 7 -7 ; "format"
41 [18] MOVE 8 4
42 [18] MOVE 9 5
43 [18] CALL 7 3 0
44 [18] CALL 6 0 1
45 [21] RETURN 5 2
46 [22] RETURN 0 1
Bonjour le monde
C’est bonjour le code mondial :
print("Hello World!")
Comment ça fonctionne? C’est simple!
Lua exécute la fonction print()
et utilise la chaîne "Hello World"
comme argument.