Lua Samouczek
Pierwsze kroki z Luą
Szukaj…
Uwagi
Lua to minimalistyczny, lekki i możliwy do osadzenia język skryptowy. Jest projektowany, wdrażany i utrzymywany przez zespół z PUC-Rio , Papieskiego Katolickiego Uniwersytetu Rio de Janeiro w Brazylii. Lista mailingowa jest otwarta, aby się zaangażować.
Typowe przypadki użycia dla Lua obejmują pisanie skryptów gier wideo, rozszerzanie aplikacji o wtyczki i konfiguracje, pakowanie logiki biznesowej wysokiego poziomu lub po prostu osadzanie w urządzeniach takich jak telewizory, samochody itp.
W przypadku zadań o wysokiej wydajności istnieje niezależna implementacja za pomocą kompilatora just-in-time o nazwie LuaJIT .
Wersje
Wersja | Notatki | Data wydania |
---|---|---|
1.0 | Pierwsze, niepubliczne wydanie. | 1993-07-28 |
1.1 | Pierwsze publiczne wydanie. Dokument konferencyjny opisujący to. | 1994-07-08 |
2.1 | Począwszy od Lua 2.1, Lua stał się swobodnie dostępny do wszystkich celów, w tym do zastosowań komercyjnych. Gazeta opisująca to. | 1995-02-07 |
2.2 | Długie ciągi, interfejs debugowania, lepsze śledzenie stosu | 1995-11-28 |
2.4 | Zewnętrzny kompilator luac | 1996-05-14 |
2.5 | Funkcje dopasowania wzorców i vararg. | 1996-11-19 |
3.0 | Wprowadzono auxlib, bibliotekę pomagającą pisać biblioteki Lua | 01.07.1997 |
3.1 | Anonimowe funkcje i zamknięcia funkcji poprzez „podwyższenie wartości”. | 1998-07-11 |
3.2 | Debuguj bibliotekę i nowe funkcje tabeli | 1999-07-08 |
3.2.2 | 2000-02-22 | |
4.0 | Wiele stanów, instrukcje „for”, aktualizacja interfejsu API. | 2000-11-06 |
4.0.1 | 2002-07-04 | |
5.0 | Coroutines, metatables, pełny zakres leksykalny, ogony, booleany przechodzą na licencję MIT. | 2003-04-11 |
5.0.3 | 2006-06-26 | |
5.1 | Modernizacja systemu modułów, przyrostowy moduł wyrzucania elementów bezużytecznych, metatable dla wszystkich typów, przeróbka luaconf.h, parser w pełni poprawny, argumenty variadic. | 2006-02-21 |
5.1.5 | 17.02.2012 | |
5.2 | Awaryjny pojemnik na śmieci, goto, finalizatory tabel. | 16.12.2011 |
5.2.4 | 2015-03-07 | |
5.3 | Podstawowa obsługa UTF-8, operacje bitowe, liczby całkowite 32 / 64bit. | 2015-01-12 |
5.3.4 | Ostatnia wersja. | 2017-01-12 |
Instalacja
Pliki binarne
Pliki binarne Lua są dostarczane przez większość dystrybucji GNU / Linux jako pakiet.
Na przykład w Debianie, Ubuntu i ich pochodnych można je uzyskać, wykonując to:
sudo apt-get install lua50
sudo apt-get install lua51
sudo apt-get install lua52
Istnieje kilka półoficjalnych wersji dla Windows, MacOS i niektórych innych systemów operacyjnych hostowanych w SourceForge .
Użytkownicy Apple mogą również łatwo zainstalować Lua za pomocą Homebrew :
brew install lua
(Obecnie Homebrew ma 5.2.4, dla 5.3 patrz Homebrew / wersje .)
Źródło
Źródło jest dostępne na oficjalnej stronie . Pozyskiwanie źródeł i samej kompilacji powinno być trywialne. W systemach Linux wystarczające powinny być:
$ 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
W powyższym przykładzie w zasadzie pobieramy źródłowy tarball
z oficjalnej strony, weryfikujemy jego sumę kontrolną oraz wyodrębniamy i wykonujemy make
. (Sprawdź dwukrotnie sumę kontrolną na oficjalnej stronie ).
Uwaga: musisz określić, jaki cel kompilacji chcesz. W tym przykładzie podaliśmy linux
. Inne dostępne cele kompilacji to solaris
, aix
, bsd
, freebsd
, macosx
, mingw
itp. Więcej informacji można znaleźć w doc/readme.html
, który znajduje się w źródle. ( Najnowszą wersję README można również znaleźć w Internecie .)
Moduły
Standardowe biblioteki są ograniczone do prymitywów:
-
coroutine
- funkcjonalność zarządzania coroutine -
debug
- zaczepy i narzędzia do debugowania -
io
- podstawowe operacje podstawowe IO -
package
- funkcjonalność zarządzania modułem -
string
- funkcja dopasowywania wzorca do łańcucha i Lua -
table
- prymitywy do radzenia sobie z niezbędnymi, ale złożonymi tabelami typu Lua -
os
- podstawowe operacje systemu operacyjnego -
utf8
- podstawowe prymitywy UTF-8 (od Lua 5.3)
Wszystkie te biblioteki można wyłączyć dla określonej kompilacji lub załadować w czasie wykonywania.
Biblioteki Lua innych firm i infrastruktura do dystrybucji modułów są rzadkie, ale poprawiają się. Projekty takie jak LuaRocks , Lua Toolbox i LuaDist poprawiają sytuację. Wiele informacji i sugestii można znaleźć na starszej Wiki Lua , ale pamiętaj, że niektóre z tych informacji są dość stare i nieaktualne.
Komentarze
Komentarze jednowierszowe w Lua zaczynają się od --
i trwają do końca linii:
-- this is single line comment
-- need another line
-- huh?
Blokowanie komentarzy zaczyna się od --[[
i kończy się na ]]
:
--[[
This is block comment.
So, it can go on...
and on...
and on....
]]
Komentarze blokowe używają tego samego stylu separatorów co długie łańcuchy; między nawiasami można dodać dowolną liczbę znaków równości, aby wyznaczyć komentarz:
--[=[
This is also a block comment
We can include "]]" inside this comment
--]=]
--[==[
This is also a block comment
We can include "]=]" inside this comment
--]==]
Zgrabną sztuczką do komentowania fragmentów kodu jest otaczanie go --[[
i --]]
:
--[[
print'Lua is lovely'
--]]
Aby ponownie aktywować fragment, po prostu dodaj -
do sekwencji otwierającej komentarz:
---[[
print'Lua is lovely'
--]]
W ten sposób sekwencja --
w pierwszym wierszu rozpoczyna komentarz jednowierszowy, podobnie jak ostatni wiersz, a instrukcja print
nie jest komentowana.
Idąc o krok dalej, dwa bloki kodu można skonfigurować w taki sposób, że jeśli pierwszy blok zostanie skomentowany, drugi nie będzie, i odwrotnie:
---[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Aby uaktywnić drugi fragment, wyłączając pierwszy fragment, usuń wiodące -
w pierwszym wierszu:
--[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Wykonywanie programów Lua
Zwykle Lua jest wysyłana z dwoma plikami binarnymi:
-
lua
- samodzielny interpreter i interaktywna powłoka -
luac
- kompilator kodu bajtowego
Powiedzmy, że mamy przykładowy program ( bottles_of_mate.lua
) taki jak ten:
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
Sam program można uruchomić, wykonując następujące czynności w powłoce:
$ lua bottles_of_mate.lua
Dane wyjściowe powinny wyglądać tak, działając w nieskończonej pętli:
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.
...
Możesz skompilować program do kodu bajtowego Lua, wykonując następujące czynności w swojej powłoce:
$ luac bottles_of_mate.lua -o bottles_of_mate.luac
Dostępna jest również lista kodów bajtowych, wykonując następujące czynności:
$ 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
Pierwsze kroki
zmienne
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.
typy
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!"
Specjalny typ nil
Innym typem w Lua jest nil
. Wartość tylko w nil
typu jest nil
. nil
istnieje, aby różnić się od wszystkich innych wartości w Lua. Jest to rodzaj wartości bez wartości.
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!
wyrażenia
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
Definiowanie funkcji
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
booleany
Tylko false
i nil
traktowane jako fałsz, wszystko inne, w tym 0
i pusty ciąg znaków, są traktowane jako prawda.
zbieranie śmieci
tab = {"lots", "of", "data"}
tab = nil; collectgarbage()
-- tab does no longer exist, and doesn't take up memory anymore.
stoły
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.
To są podstawy, ale jest sekcja o tabelach z dodatkowymi informacjami.
warunki
if (condition) then
-- do something
elseif (other_condition) then
-- do something else
else
-- do something
end
dla pętli
Istnieją dwa typy pętli for
w Lua: numeryczna for
pętli i ogólna for
pętli.
Liczbowy
for
pętli ma postać następującą: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
Trzecie wyrażenie w liczbowej pętli
for
jest krokiem, o który pętla będzie się zwiększać. Ułatwia to wykonywanie pętli zwrotnych:for a=10, 1, -1 do print(a) --> 10, 9, 8, 7, 6, etc. end
Jeśli wyrażenie kroku zostanie pominięte, Lua przyjmuje domyślny krok 1.
for a=1, 10 do print(a) --> 1, 2, 3, 4, 5, etc. end
Zauważ również, że zmienna pętli jest lokalna
for
pętlifor
. Nie będzie istniał po zakończeniu pętli.
Ogólny
for
pętli działa na wszystkich wartościach zwracanych przez funkcję iteratora:for key, value in pairs({"some", "table"}) do print(key, value) --> 1 some --> 2 table end
Lua zapewnia kilka wbudowanych iteratorów (np.
pairs
,pairs
ipairs
), a użytkownicy mogą definiować własne niestandardowe iteratory, aby używać ich z ogólnymifor
pętli.
robić bloki
local a = 10
do
print(a) --> 10
local a = 20
print(a) --> 20
end
print(a) --> 10
Niektóre trudne rzeczy
Czasami Lua nie zachowuje się tak, jak można by pomyśleć po przeczytaniu dokumentacji. Niektóre z tych przypadków to:
Zero i Nic nie są takie same (WSPÓLNY PITFALL!)
Zgodnie z oczekiwaniami table.insert(my_table, 20)
dodaje wartość 20
do tabeli, a table.insert(my_table, 5, 20)
dodaje wartość 20 na 5. pozycji. Co jednak robi table.insert(my_table, 5, nil)
? Można się spodziewać, że będzie traktować nil
jako żaden argument i wstawi wartość 5
na końcu tabeli, ale w rzeczywistości dodaje wartość nil
na 5. pozycji tabeli. Kiedy to jest problem?
(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)
Podobnie dzieje się z 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
Może to również prowadzić do błędów podczas korzystania z kodu strony trzeciej. Jeśli, na przykład, dokumentacja niektórych funkcji stwierdza „zwraca pączki, jeśli ma szczęście, w przeciwnym razie zero”, implementacja może wyglądać mniej więcej tak
function func(lucky)
if lucky then
return "donuts"
end
end
to wdrożenie może początkowo wydawać się rozsądne; zwraca pączki, gdy jest to konieczne, a po wpisaniu result = func(false)
wynik będzie zawierał wartość nil
.
Gdyby jednak napisać print(tostring(func(false)))
lua wyrzuciłby błąd, który wygląda stdin:1: bad argument #1 to 'tostring' (value expected)
tak stdin:1: bad argument #1 to 'tostring' (value expected)
Dlaczego? tostring
wyraźnie otrzymuje argument, mimo że jest nil
. Źle. func w ogóle nic nie zwraca, więc tostring(func(false))
jest taki sam jak tostring()
i NIE jest taki sam jak tostring(nil)
.
Błędy mówiące o „oczekiwanej wartości” są silnym sygnałem, że może to być przyczyną problemu.
Pozostawiając luki w tablicach
To wielka pułapka, jeśli jesteś nowy w lua, aw kategorii tabel jest wiele informacji
Witaj świecie
To jest kod cześć świata:
print("Hello World!")
Jak to działa? To proste! Lua wykonuje funkcję print()
i wykorzystuje ciąg "Hello World"
jako argument.