Lua Zelfstudie
Aan de slag met Lua
Zoeken…
Opmerkingen
Lua is minimalistische, lichtgewicht en insluitbare scripttaal. Het wordt ontworpen, geïmplementeerd en onderhouden door een team van PUC-Rio , de Pauselijke Katholieke Universiteit van Rio de Janeiro in Brazilië. De mailinglijst staat open om mee te doen.
Veelvoorkomende use-cases voor Lua omvatten scripting videogames, uitbreiding van applicaties met plug-ins en configs, inpakken van een aantal bedrijfslogica op hoog niveau of gewoon inbedden in apparaten zoals tv's, auto's, etc.
Voor taken met hoge prestaties is er onafhankelijke implementatie met behulp van just-in-time-compiler beschikbaar genaamd LuaJIT .
versies
Versie | Notes | Publicatiedatum |
---|---|---|
1.0 | Eerste, niet-openbare release. | 1993/07/28 |
1.1 | Eerste publieke release. Conferentiedocument dat het beschrijft. | 1994/07/08 |
2.1 | Vanaf Lua 2.1 werd Lua vrij beschikbaar voor alle doeleinden, inclusief commercieel gebruik. Journal paper beschrijft het. | 1995/02/07 |
2.2 | Lange reeksen, de foutopsporingsinterface, betere stapel-tracebacks | 1995/11/28 |
2.4 | Externe luac compiler | 1996/05/14 |
2.5 | Patroonaanpassing en vararg-functies. | 1996/11/19 |
3.0 | Introductie van auxlib, een bibliotheek voor het schrijven van Lua-bibliotheken | 1997/07/01 |
3.1 | Anonieme functies en functiesluitingen via "waarden". | 1998/07/11 |
3.2 | Foutopsporingsbibliotheek en nieuwe tabelfuncties | 1999/07/08 |
3.2.2 | 2000/02/22 | |
4.0 | Meerdere statussen, "voor" -instructies, API-vernieuwing. | 2000/11/06 |
4.0.1 | 2002/07/04 | |
5.0 | Coroutines, metatables, volledige lexicale scoping, staartoproepen, booleans gaan naar MIT-licentie. | 2003/04/11 |
5.0.3 | 2006-06-26 | |
5.1 | Vernieuwing van modulesysteem, incrementele afvalverzamelaar, metatabellen voor alle typen, luaconf.h-vernieuwing, volledig reentrant parser, variadische argumenten. | 2006-02-21 |
5.1.5 | 2012-02-17 | |
5.2 | Noodafvalverzamelaar, ga naar, finalizers voor tafels. | 2011-12-16 |
5.2.4 | 2015/03/07 | |
5.3 | Basis UTF-8 ondersteuning, bitgewijze ops, 32 / 64bit gehele getallen. | 2015/01/12 |
5.3.4 | Laatste versie. | 2017/01/12 |
Installatie
binaries
Lua binaries worden door de meeste GNU / Linux-distributies als een pakket aangeboden.
Op Debian, Ubuntu en hun derivaten kan het bijvoorbeeld worden verkregen door dit uit te voeren:
sudo apt-get install lua50
sudo apt-get install lua51
sudo apt-get install lua52
Er zijn enkele semi-officiële builds beschikbaar voor Windows, MacOS en enkele andere besturingssystemen die worden gehost bij SourceForge .
Apple-gebruikers kunnen Lua ook eenvoudig installeren met Homebrew :
brew install lua
(Momenteel heeft Homebrew 5.2.4, zie 5.3 voor Homebrew / versies .)
Bron
Bron is beschikbaar op de officiële pagina . Acquisitie van bronnen en zelf bouwen moet triviaal zijn. Op Linux-systemen moet het volgende voldoende zijn:
$ 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
In het bovenstaande voorbeeld downloaden we in feite een bron- tarball
van de officiële site, verifiëren we de controlesom en extraheren en voeren we het make
. (Controleer de controlesom op de officiële pagina .)
Opmerking: u moet opgeven welk builddoel u wilt. In het voorbeeld hebben we linux
gespecificeerd. Andere beschikbare macosx
zijn solaris
, aix
, bsd
, freebsd
, macosx
, mingw
, etc. Bekijk doc/readme.html
, dat is opgenomen in de bron, voor meer informatie. (U kunt ook de nieuwste versie van de README online vinden .)
modules
Standaardbibliotheken zijn beperkt tot primitieven:
-
coroutine
- coroutinebeheerfunctionaliteit -
debug
- debug hooks and tools -
io
- basis IO-primitieven -
package
- modulebeheerfunctionaliteit -
string
- string en Lua-specifieke functionaliteit voor patroonovereenkomst -
table
- primitieven voor het omgaan met een essentieel maar complex Lua type - tabellen -
os
- basis OS-bewerkingen -
utf8
- basis UTF-8 primitieven (sinds Lua 5.3)
Al die bibliotheken kunnen voor een specifieke build worden uitgeschakeld of tijdens uitvoering worden geladen.
Lua-bibliotheken van derden en infrastructuur voor het distribueren van modules is schaars, maar verbetert. Projecten zoals LuaRocks , Lua Toolbox en LuaDist verbeteren de situatie. Veel informatie en veel suggesties zijn te vinden op de oudere Lua Wiki , maar houd er rekening mee dat sommige van deze informatie vrij oud en verouderd is.
Comments
Opmerkingen over één regel in Lua beginnen met --
en gaan door tot het einde van de regel:
-- this is single line comment
-- need another line
-- huh?
Blok reacties beginnen met --[[
en eindigen met ]]
:
--[[
This is block comment.
So, it can go on...
and on...
and on....
]]
Blokopmerkingen gebruiken dezelfde stijl van scheidingstekens als lange tekenreeksen; een willekeurig aantal gelijke tekens kan tussen de haakjes worden toegevoegd om een opmerking af te bakenen:
--[=[
This is also a block comment
We can include "]]" inside this comment
--]=]
--[==[
This is also a block comment
We can include "]=]" inside this comment
--]==]
Een handige truc om stukjes code te becommentariëren, is omringen met --[[
en --]]
:
--[[
print'Lua is lovely'
--]]
Om de chunk opnieuw te activeren, voeg je eenvoudig een -
aan de volgorde van het openen van reacties:
---[[
print'Lua is lovely'
--]]
Op deze manier start de volgorde --
in de eerste regel een opmerking van één regel, net als de laatste regel, en wordt er geen commentaar op de print
instructie gegeven.
Als we nog een stap verder gaan, kunnen twee codeblokken zodanig worden ingesteld dat als het eerste blok wordt becommentarieerd, het tweede niet zal zijn, en omgekeerd:
---[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Om de tweede chunk te activeren terwijl u de eerste chunk uitschakelt, verwijdert u de eerste -
op de eerste regel:
--[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Lua-programma's uitvoeren
Gewoonlijk wordt Lua verzonden met twee binaire bestanden:
-
lua
- zelfstandige tolk en interactieve shell -
luac
- bytecode compiler
Laten we zeggen dat we een voorbeeldprogramma ( bottles_of_mate.lua
) als dit hebben:
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
Het programma zelf kan worden uitgevoerd door het volgende uit te voeren op uw shell:
$ lua bottles_of_mate.lua
De uitvoer moet er zo uitzien, in de eindeloze lus:
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.
...
Je kunt het programma compileren in Lua's bytecode door het volgende uit te voeren op je shell:
$ luac bottles_of_mate.lua -o bottles_of_mate.luac
Ook is een bytecode-lijst beschikbaar door het volgende uit te voeren:
$ 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
Ermee beginnen
variabelen
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.
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!"
Het speciale type nil
Een ander type in Lua is nil
. De enige waarde in het nil
is nil
. nil
bestaat anders dan alle andere waarden in Lua. Het is een soort niet-waarde.
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!
uitdrukkingen
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
Functies definiëren
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
booleans
Alleen false
en nil
evalueren als onwaar, al het andere, inclusief 0
en de lege string evalueren als waar.
garbage-collection
tab = {"lots", "of", "data"}
tab = nil; collectgarbage()
-- tab does no longer exist, and doesn't take up memory anymore.
tafels
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.
Dit zijn de basisprincipes, maar er is een sectie over tabellen met meer informatie.
voorwaarden
if (condition) then
-- do something
elseif (other_condition) then
-- do something else
else
-- do something
end
voor lussen
Er zijn twee soorten for
lus in Lua: een numerieke for
lus en een generieke for
lus.
Een numeriek
for
lus heeft de volgende vorm: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
De derde uitdrukking in een numeriek
for
lus is de stap waarmee de lus wordt opgehoogd. Dit maakt het gemakkelijk om reverse loops te doen:for a=10, 1, -1 do print(a) --> 10, 9, 8, 7, 6, etc. end
Als de stapuitdrukking wordt weggelaten, gaat Lua uit van een standaardstap van 1.
for a=1, 10 do print(a) --> 1, 2, 3, 4, 5, etc. end
Merk ook op dat de lusvariabele lokaal is voor de
for
lus. Het zal niet bestaan nadat de lus voorbij is.
Algemeen
for
lussen werken door alle waarden die een iteratorfunctie retourneert:for key, value in pairs({"some", "table"}) do print(key, value) --> 1 some --> 2 table end
Lua biedt verschillende ingebouwde iterators (bijv.
pairs
,ipairs
), en gebruikers kunnen ook hun eigen aangepaste iterators definiëren voor gebruik met generiekefor
loops.
blokken doen
local a = 10
do
print(a) --> 10
local a = 20
print(a) --> 20
end
print(a) --> 10
Enkele lastige dingen
Soms gedraagt Lua zich niet zoals men zou denken na het lezen van de documentatie. Sommige van deze gevallen zijn:
Nul en niets zijn niet hetzelfde (COMMON PITFALL!)
Zoals verwacht, table.insert(my_table, 20)
de waarde 20
aan de tabel, en table.insert(my_table, 5, 20)
voegt de waarde 20 toe op de 5e positie. Wat doet table.insert(my_table, 5, nil)
echter? Je zou verwachten dat het nil
als helemaal geen argument behandelt en de waarde 5
aan het einde van de tabel invoegt, maar het voegt eigenlijk de waarde nil
op de 5e positie van de tabel. Wanneer is dit een probleem?
(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)
Hetzelfde gebeurt met 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
Dit kan ook leiden tot fouten bij het gebruik van code van derden. Als, bijvoorbeeld, de documentatie van een functie staten "returns donuts als je geluk hebt, niets anders", de uitvoering macht ziet er ongeveer als volgt
function func(lucky)
if lucky then
return "donuts"
end
end
deze implementatie lijkt in eerste instantie redelijk; het retourneert donuts wanneer het moet, en wanneer u result = func(false)
resultaat zal de waarde nil
bevatten.
Als iemand echter print(tostring(func(false)))
zou schrijven print(tostring(func(false)))
zou lua een foutmelding geven die er ongeveer zo uitziet als deze stdin:1: bad argument #1 to 'tostring' (value expected)
Waarom is dat? tostring
krijgt duidelijk een argument, ook al is het nil
. Mis. func retourneert helemaal niets, dus tostring(func(false))
is hetzelfde als tostring()
en NIET hetzelfde als tostring(nil)
.
Fouten die zeggen "waarde verwacht" zijn een sterke indicatie dat dit de oorzaak van het probleem kan zijn.
Gaten achterlaten in arrays
Dit is een enorme valkuil als je nieuw bent bij lua, en er is veel informatie in de tabellencategorie
Hallo Wereld
Dit is hallo wereldcode:
print("Hello World!")
Hoe het werkt? Het is makkelijk! Lua voert print()
functie print()
uit en gebruikt "Hello World"
tekenreeks "Hello World"
als argument.