Lua - Szybki przewodnik
Lua to rozszerzalny, lekki język programowania napisany w C. Rozpoczął się jako własny projekt w 1993 roku przez Roberto Ierusalimschy, Luiz Henrique de Figueiredo i Waldemara Celesa.
Został zaprojektowany od początku jako oprogramowanie, które można zintegrować z kodem napisanym w C i innych konwencjonalnych językach. Taka integracja przynosi wiele korzyści. Nie próbuje robić tego, co C już potrafi, ale ma na celu oferowanie tego, w czym C nie jest dobry: dobra odległość od sprzętu, struktury dynamiczne, brak nadmiarowości, łatwość testowania i debugowania. W tym celu Lua ma bezpieczne środowisko, automatyczne zarządzanie pamięcią i dobre udogodnienia do obsługi ciągów i innych rodzajów danych o dynamicznym rozmiarze.
funkcje
Lua zapewnia zestaw unikalnych funkcji, które odróżniają go od innych języków. Należą do nich -
- Extensible
- Simple
- Efficient
- Portable
- Wolne i otwarte
Przykładowy kod
print("Hello World!")
Jak wdrażany jest Lua?
Lua składa się z dwóch części - części zawierającej interpreter Lua i działającego systemu oprogramowania. Funkcjonujący system oprogramowania to rzeczywista aplikacja komputerowa, która może interpretować programy napisane w języku programowania Lua. Interpreter Lua jest napisany w ANSI C, dzięki czemu jest wysoce przenośny i może działać na szerokim spektrum urządzeń, od wysokiej klasy serwerów sieciowych po małe urządzenia.
Zarówno język Lua, jak i jego interpreter są dojrzałe, małe i szybkie. Wyewoluował z innych języków programowania i najwyższych standardów oprogramowania. Niewielki rozmiar umożliwia działanie na małych urządzeniach z małą ilością pamięci.
Nauka Lua
Najważniejszym punktem podczas nauki Lua jest skupienie się na koncepcjach bez zagubienia się w szczegółach technicznych.
Celem nauki języka programowania jest stać się lepszym programistą; to znaczy stać się bardziej efektywnym w projektowaniu i wdrażaniu nowych systemów oraz w utrzymywaniu starych.
Niektóre zastosowania Lua
Programowanie gier
Skrypty w aplikacjach samodzielnych
Skrypty w sieci
Rozszerzenia i dodatki do baz danych, takich jak MySQL Proxy i MySQL WorkBench
Systemy bezpieczeństwa, takie jak system wykrywania włamań.
Konfiguracja środowiska lokalnego
Jeśli nadal chcesz skonfigurować swoje środowisko dla języka programowania Lua, potrzebujesz następującego oprogramowania dostępnego na komputerze - (a) Edytor tekstu, (b) Interpreter Lua i (c) Kompilator Lua.
Edytor tekstu
Do wpisania programu potrzebny jest edytor tekstu. Przykłady kilku edytorów obejmują Notatnik Windows, polecenie edycji systemu operacyjnego, Brief, Epsilon, EMACS i vim lub vi.
Nazwa i wersja edytora tekstu mogą się różnić w różnych systemach operacyjnych. Na przykład Notatnik będzie używany w systemie Windows, a vim lub vi może być używany zarówno w systemie Windows, jak i Linux lub UNIX.
Pliki utworzone za pomocą edytora nazywane są plikami źródłowymi, a te pliki zawierają kod źródłowy programu. Pliki źródłowe programów Lua są zwykle nazywane z rozszerzeniem".lua".
Tłumacz Lua
To tylko mały program, który umożliwia wpisywanie poleceń Lua i natychmiastowe ich wykonanie. Zatrzymuje wykonanie pliku Lua w przypadku napotkania błędu, w przeciwieństwie do kompilatora, który wykonuje w pełni.
Kompilator Lua
Kiedy rozszerzamy Lua na inne języki / aplikacje, potrzebujemy Software Development Kit z kompilatorem kompatybilnym z Lua Application Program Interface.
Instalacja w systemie Windows
Istnieje oddzielne IDE o nazwie „SciTE” opracowane dla środowiska Windows, które można pobrać z witryny https://code.google.com/p/luaforwindows/ sekcja pobierania.
Uruchom pobrany plik wykonywalny, aby zainstalować Lua IDE.
Ponieważ jest to IDE, możesz zarówno tworzyć, jak i budować kod Lua przy użyciu tego samego.
W przypadku, gdy chcesz zainstalować Lua w trybie wiersza poleceń, musisz zainstalować MinGW lub Cygwin, a następnie skompilować i zainstalować Lua w systemie Windows.
Instalacja w systemie Linux
Aby pobrać i zbudować Lua, użyj następującego polecenia -
$ wget http://www.lua.org/ftp/lua-5.2.3.tar.gz $ tar zxf lua-5.2.3.tar.gz
$ cd lua-5.2.3 $ make linux test
Aby zainstalować na innych platformach, takich jak aix, ansi, bsd, generic linux, mingw, posix, solaris, zastępując Linuksa w make Linux, przetestuj z odpowiednią nazwą platformy.
Mamy helloWorld.lua w Lua w następujący sposób -
print("Hello World!")
Teraz możemy zbudować i uruchomić plik Lua, powiedz helloWorld.lua, przełączając się do folderu zawierającego plik za pomocą cd, a następnie używając następującego polecenia -
$ lua helloWorld
Widzimy następujący wynik.
Hello World!
Instalacja w systemie Mac OS X
Aby zbudować / przetestować Lua w systemie Mac OS X, użyj następującego polecenia -
$ curl -R -O http://www.lua.org/ftp/lua-5.2.3.tar.gz
$ tar zxf lua-5.2.3.tar.gz $ cd lua-5.2.3
$ make macosx test
W niektórych przypadkach może nie być zainstalowane Xcode i narzędzia wiersza poleceń. W takich przypadkach nie będzie można użyć polecenia make. Zainstaluj Xcode z Mac App Store. Następnie przejdź do Preferencji Xcode, a następnie przejdź do Pobrania i zainstaluj komponent o nazwie „Narzędzia wiersza poleceń”. Po zakończeniu procesu polecenie make będzie dostępne.
Wykonywanie instrukcji „make macosx test” nie jest obowiązkowe. Nawet bez wykonywania tego polecenia nadal możesz używać Lua w systemie Mac OS X.
Mamy helloWorld.lua w Lua w następujący sposób -
print("Hello World!")
Teraz możemy zbudować i uruchomić plik Lua, powiedz helloWorld.lua, przełączając się do folderu zawierającego plik za pomocą cd, a następnie używając następującego polecenia -
$ lua helloWorld
Możemy zobaczyć następujące dane wyjściowe -
Hello World!
Lua IDE
Jak wspomniano wcześniej, dla Windows SciTE, Lua IDE jest domyślnym IDE dostarczonym przez zespół twórców Lua. Dostępne alternatywne IDE pochodzi z ZeroBrane Studio, które jest dostępne na wielu platformach, takich jak Windows, Mac i Linux.
Istnieją również wtyczki do zaćmienia, które umożliwiają rozwój Lua. Korzystanie ze środowiska IDE ułatwia programowanie dzięki funkcjom takim jak uzupełnianie kodu i jest wysoce zalecane. IDE zapewnia również programowanie w trybie interaktywnym, podobne do wersji Lua z wiersza poleceń.
Zacznijmy tworzyć nasz pierwszy program Lua!
Pierwszy program Lua
Programowanie w trybie interaktywnym
Lua udostępnia tryb zwany trybem interaktywnym. W tym trybie możesz wpisywać instrukcje jedna po drugiej i uzyskiwać natychmiastowe wyniki. Można to wywołać w powłoce za pomocą polecenia lua -i lub po prostu polecenia lua. Po wpisaniu tego, naciśnij Enter, a tryb interaktywny zostanie uruchomiony, jak pokazano poniżej.
$ lua -i $ Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
quit to end; cd, dir and edit also available
Możesz coś wydrukować, korzystając z następującego oświadczenia -
print("test")
Po naciśnięciu klawisza Enter otrzymasz następujące dane wyjściowe -
test
Programowanie w trybie domyślnym
Wywołanie interpretera z parametrem nazwy pliku Lua rozpoczyna wykonywanie pliku i trwa do zakończenia skryptu. Po zakończeniu skryptu interpreter nie jest już aktywny.
Napiszmy prosty program w Lua. Wszystkie pliki Lua będą miały rozszerzenie .lua. Więc umieść następujący kod źródłowy w pliku test.lua.
print("test")
Zakładając, że środowisko lua jest poprawnie skonfigurowane, uruchommy program za pomocą następującego kodu -
$ lua test.lua
Otrzymamy następujący wynik -
test
Wypróbujmy inny sposób wykonania programu Lua. Poniżej znajduje się zmodyfikowany plik test.lua -
#!/usr/local/bin/lua
print("test")
Tutaj założyliśmy, że masz dostępny interpreter Lua w swoim katalogu / usr / local / bin. Pierwsza linia jest ignorowana przez interpreter, jeśli zaczyna się od znaku #. Teraz spróbuj uruchomić ten program w następujący sposób -
$ chmod a+rx test.lua
$./test.lua
Otrzymamy następujący wynik.
test
Zobaczmy teraz podstawową strukturę programu Lua, tak aby było Ci łatwo zrozumieć podstawowe elementy składowe języka programowania Lua.
Żetony w Lua
Program Lua składa się z różnych tokenów, a token jest słowem kluczowym, identyfikatorem, stałą, literałem ciągu lub symbolem. Na przykład następująca instrukcja Lua składa się z trzech tokenów -
io.write("Hello world, from ",_VERSION,"!\n")
Poszczególne żetony to -
io.write
(
"Hello world, from ",_VERSION,"!\n"
)
Komentarze
Komentarze są jak tekst pomocy w programie Lua i są ignorowane przez interpretera. Zaczynają się od - [[i kończą znakami -]], jak pokazano poniżej -
--[[ my first program in Lua --]]
Identyfikatory
Identyfikator Lua to nazwa używana do identyfikacji zmiennej, funkcji lub innego elementu zdefiniowanego przez użytkownika. Identyfikator zaczyna się od litery „A do Z” lub „od a do z” lub podkreślenia „_”, po której następuje zero lub więcej liter, podkreśleń i cyfr (od 0 do 9).
Lua nie zezwala na znaki interpunkcyjne, takie jak @, $ i% w identyfikatorach. Lua jestcase sensitivejęzyk programowania. Zatem siła robocza i siła robocza to dwa różne identyfikatory w Lua. Oto kilka przykładów akceptowanych identyfikatorów -
mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal
Słowa kluczowe
Poniższa lista przedstawia kilka słów zastrzeżonych w Lua. Te zastrzeżone słowa nie mogą być używane jako stałe lub zmienne ani żadne inne nazwy identyfikatorów.
i | przerwa | zrobić | jeszcze |
elseif | koniec | fałszywy | dla |
funkcjonować | gdyby | w | lokalny |
zero | nie | lub | powtarzać |
powrót | następnie | prawdziwe | aż do |
podczas |
Białe spacje w Lua
Linia zawierająca tylko białe spacje, prawdopodobnie z komentarzem, jest nazywana pustą linią, a interpreter Lua całkowicie ją ignoruje.
Białe znaki to termin używany w Lua do opisywania spacji, tabulatorów, znaków nowej linii i komentarzy. Biała spacja oddziela jedną część instrukcji od drugiej i umożliwia interpretatorowi określenie, gdzie kończy się jeden element instrukcji, taki jak int, a zaczyna następny. Dlatego w poniższym oświadczeniu -
local age
Aby tłumacz mógł je rozróżnić, musi istnieć co najmniej jeden znak odstępu (zwykle spacja) między określeniem lokalnym a wiekiem. Z drugiej strony w poniższym stwierdzeniu -
fruit = apples + oranges --get the total fruit
Pomiędzy owocami a = lub między = a jabłkami nie są potrzebne żadne spacje, chociaż możesz je dodać, jeśli chcesz, aby były czytelne.
Zmienna to nic innego jak nazwa nadana obszarowi pamięci, którym nasze programy mogą manipulować. Może zawierać różne typy wartości, w tym funkcje i tabele.
Nazwa zmiennej może składać się z liter, cyfr i znaku podkreślenia. Musi zaczynać się od litery lub podkreślenia. Wielkie i małe litery są różne, ponieważ Lua rozróżnia wielkość liter. W Lua istnieje osiem podstawowych typów wartości -
W Lua, chociaż nie mamy zmiennych typów danych, mamy trzy typy oparte na zakresie zmiennej.
Global variables - Wszystkie zmienne są uważane za globalne, chyba że zostały wyraźnie zadeklarowane jako lokalne.
Local variables - Gdy typ jest określony jako lokalny dla zmiennej, jej zakres jest ograniczony funkcjami wewnątrz ich zakresu.
Table fields - Jest to specjalny typ zmiennej, która może przechowywać wszystko oprócz nil, w tym funkcje.
Definicja zmiennej w Lua
Definicja zmiennej oznacza poinformowanie interpretera, gdzie i ile ma utworzyć pamięć dla zmiennej. Definicja zmiennej ma typ opcjonalny i zawiera listę co najmniej jednej zmiennej tego typu w następujący sposób -
type variable_list;
Tutaj, type jest opcjonalnie lokalny lub określony przez typ, dzięki czemu jest globalny, a variable_listmoże składać się z jednej lub więcej nazw identyfikatorów oddzielonych przecinkami. Tutaj pokazano kilka ważnych deklaracji -
local i, j
local i
local a,c
Linia local i, jdeklaruje i definiuje zmienne i i j; co instruuje interpretera, aby utworzył zmienne o nazwach i, j i ograniczał zakres do lokalnego.
Zmienne można zainicjować (przypisać wartość początkową) w ich deklaracji. Inicjator składa się ze znaku równości, po którym następuje stałe wyrażenie w następujący sposób -
type variable_list = value_list;
Oto kilka przykładów:
local d , f = 5 ,10 --declaration of d and f as local variables.
d , f = 5, 10; --declaration of d and f as global variables.
d, f = 10 --[[declaration of d and f as global variables.
Here value of f is nil --]]
W przypadku definicji bez inicjatora: zmienne ze statycznym czasem trwania przechowywania są niejawnie inicjowane wartością nil.
Deklaracja zmiennej w Lua
Jak widać w powyższych przykładach, przypisania zmiennych wielokrotnych są zgodne z formatem lista_zmiennych i lista_wartości. W powyższym przykładzielocal d, f = 5,10 mamy d i f na liście_zmiennych i 5 i 10 na liście wartości.
Przypisywanie wartości w Lua odbywa się jak pierwsza zmienna w lista_zmiennych z pierwszą wartością w liście_wartości i tak dalej. Stąd wartość d wynosi 5, a wartość f to 10.
Przykład
Wypróbuj poniższy przykład, w którym zmienne zostały zadeklarowane u góry, ale zostały zdefiniowane i zainicjowane wewnątrz funkcji głównej -
-- Variable definition:
local a, b
-- Initialization
a = 10
b = 30
print("value of a:", a)
print("value of b:", b)
-- Swapping of variables
b, a = a, b
print("value of a:", a)
print("value of b:", b)
f = 70.0/3.0
print("value of f", f)
Kiedy powyższy kod jest budowany i wykonywany, daje następujący wynik -
value of a: 10
value of b: 30
value of a: 30
value of b: 10
value of f 23.333333333333
Lvalues i Rvalues w Lua
W Lua są dwa rodzaje wyrażeń -
lvalue- Wyrażenia odnoszące się do miejsca w pamięci nazywane są wyrażeniem „l-wartość”. Wartość l może pojawić się jako lewa lub prawa strona przypisania.
rvalue- Termin rvalue odnosi się do wartości danych przechowywanych pod jakimś adresem w pamięci. Wartość r to wyrażenie, któremu nie można przypisać wartości, co oznacza, że wartość r może pojawić się po prawej stronie, ale nie po lewej stronie przypisania.
Zmienne to lvalues, więc mogą pojawiać się po lewej stronie przydziału. Literały numeryczne są wartościami r, więc nie można ich przypisywać i nie mogą pojawiać się po lewej stronie. Poniżej znajduje się prawidłowe oświadczenie -
g = 20
Ale poniższe nie jest prawidłową instrukcją i spowodowałoby błąd w czasie kompilacji -
10 = 20
W języku programowania Lua, oprócz powyższych typów przypisań, możliwe jest posiadanie wielu l-wartości i r-wartości w jednej instrukcji. Jest to pokazane poniżej.
g,l = 20,30
W powyższym zestawieniu 20 przypisano g, a 30 przypisano l.
Lua jest językiem dynamicznie typowanym, więc zmienne nie mają typów, tylko wartości mają typy. Wartości mogą być przechowywane w zmiennych, przekazywane jako parametry i zwracane jako wyniki.
W Lua, chociaż nie mamy zmiennych typów danych, ale mamy typy dla wartości. Lista typów danych dla wartości jest podana poniżej.
Sr.No | Typ i opis wartości |
---|---|
1 | nil Służy do odróżniania wartości od posiadania pewnych danych lub braku (zerowych) danych. |
2 | boolean Uwzględnia true i false jako wartości. Zwykle używany do sprawdzania stanu. |
3 | number Reprezentuje liczby rzeczywiste (zmiennoprzecinkowe o podwójnej precyzji). |
4 | string Reprezentuje tablicę znaków. |
5 | function Reprezentuje metodę napisaną w C lub Lua. |
6 | userdata Reprezentuje dowolne dane C. |
7 | thread Reprezentuje niezależne wątki wykonania i służy do implementacji programów. |
8 | table Reprezentuj zwykłe tablice, tabele symboli, zbiory, rekordy, wykresy, drzewa itp. Oraz implementuje tablice asocjacyjne. Może mieć dowolną wartość (oprócz zera). |
Typ Funkcja
W Lua istnieje funkcja o nazwie „typ”, która pozwala nam poznać typ zmiennej. W poniższym kodzie podano kilka przykładów.
print(type("What is my type")) --> string
t = 10
print(type(5.8*t)) --> number
print(type(true)) --> boolean
print(type(print)) --> function
print(type(nil)) --> nil
print(type(type(ABC))) --> string
Kiedy budujesz i uruchamiasz powyższy program, daje on następujący wynik w systemie Linux -
string
number
boolean
function
nil
string
Domyślnie wszystkie zmienne będą wskazywać na zero, dopóki nie zostaną przypisane wartości lub nie zostaną zainicjowane. W Lua ciągi zerowe i puste są uważane za prawdziwe w przypadku sprawdzania warunków. Dlatego należy zachować ostrożność podczas korzystania z operacji boolowskich. Dowiemy się więcej na temat używania tych typów w następnych rozdziałach.
Operator to symbol, który mówi tłumaczowi, aby wykonał określone operacje matematyczne lub logiczne. Język Lua jest bogaty we wbudowane operatory i zapewnia następujący typ operatorów -
- Operatory arytmetyczne
- Operatorzy relacyjni
- Operatory logiczne
- Różne operatory
Ten samouczek wyjaśni po kolei operatory arytmetyczne, relacyjne, logiczne i inne różne.
Operatory arytmetyczne
Poniższa tabela przedstawia wszystkie operatory arytmetyczne obsługiwane przez język Lua. Przyjmij zmiennąA posiada 10 i zmienną B mieści wtedy 20 -
Pokaż przykłady
Operator | Opis | Przykład |
---|---|---|
+ | Dodaje dwa operandy | A + B da 30 |
- | Odejmuje drugi operand od pierwszego | A - B da -10 |
* | Pomnóż oba operandy | A * B da 200 |
/ | Podziel licznik przez de-licznik | B / A da 2 |
% | Operator modułu i reszta po dzieleniu całkowitoliczbowym | B% A da 0 |
^ | Operator wykładnika bierze potęgi | A ^ 2 da 100 |
- | Jednoargumentowy - operator działa jako negacja | -A da -10 |
Operatorzy relacyjni
Poniższa tabela przedstawia wszystkie operatory relacyjne obsługiwane przez język Lua. Przyjmij zmiennąA posiada 10 i zmienną B mieści wtedy 20 -
Pokaż przykłady
Operator | Opis | Przykład |
---|---|---|
== | Sprawdza, czy wartości dwóch operandów są równe, czy nie, jeśli tak, warunek staje się prawdziwy. | (A == B) nie jest prawdą. |
~ = | Sprawdza, czy wartości dwóch operandów są równe, czy nie, jeśli wartości nie są równe, warunek staje się prawdziwy. | (A ~ = B) jest prawdą. |
> | Sprawdza, czy wartość lewego operandu jest większa niż wartość prawego operandu, jeśli tak, warunek staje się prawdziwy. | (A> B) nie jest prawdą. |
< | Sprawdza, czy wartość lewego operandu jest mniejsza niż wartość prawego operandu. Jeśli tak, warunek staje się prawdziwy. | (A <B) jest prawdą. |
> = | Sprawdza, czy wartość lewego operandu jest większa lub równa wartości prawego operandu, jeśli tak, warunek staje się prawdziwy. | (A> = B) nie jest prawdą. |
<= | Sprawdza, czy wartość lewego operandu jest mniejsza lub równa wartości prawego operandu, jeśli tak, warunek staje się prawdziwy. | (A <= B) jest prawdą. |
Operatory logiczne
Poniższa tabela przedstawia wszystkie operatory logiczne obsługiwane przez język Lua. Przyjmij zmiennąA jest prawdziwe i zmienne B wtedy jest fałszywa -
Pokaż przykłady
Operator | Opis | Przykład |
---|---|---|
i | Nazywany operatorem logicznym AND. Jeśli oba operandy są niezerowe, warunek staje się prawdziwy. | (A i B) jest fałszem. |
lub | Nazywany operatorem logicznym OR. Jeśli którykolwiek z dwóch operandów jest różny od zera, warunek staje się prawdziwy. | (A lub B) jest prawdą. |
nie | Nazywany operatorem logicznym NOT. Służy do odwracania stanu logicznego operandu. Jeśli warunek jest spełniony, operator logiczny NOT spowoduje fałsz. | ! (A i B) jest prawdą. |
Różne operatory
Różne operatory obsługiwane przez język Lua obejmują concatenation i length.
Pokaż przykłady
Operator | Opis | Przykład |
---|---|---|
.. | Łączy dwa ciągi. | a..b, gdzie a to „Hello”, a b to „World”, zwróci „Hello World”. |
# | Operator jednoargumentowy, który zwraca długość łańcucha lub tabeli. | # „Hello” zwróci wartość 5 |
Pierwszeństwo operatorów w Lua
Pierwszeństwo operatorów określa grupowanie terminów w wyrażeniu. Ma to wpływ na sposób oceny wyrażenia. Niektórzy operatorzy mają wyższy priorytet niż inni; na przykład operator mnożenia ma wyższy priorytet niż operator dodawania -
Na przykład x = 7 + 3 * 2; Tutaj x ma przypisane 13, a nie 20, ponieważ operator * ma wyższy priorytet niż +, więc najpierw jest mnożony przez 3 * 2, a następnie sumowany do 7.
Tutaj operatory o najwyższym priorytecie pojawiają się na górze tabeli, a operatory o najniższym priorytecie - na dole. W wyrażeniu najpierw zostaną ocenione operatory o wyższym priorytecie.
Pokaż przykłady
Kategoria | Operator | Łączność |
---|---|---|
Jednoargumentowe | nie # - | Od prawej do lewej |
Powiązanie | .. | Od prawej do lewej |
Mnożny | * /% | Z lewej na prawą |
Przyłączeniowy | + - | Z lewej na prawą |
Relacyjny | <> <=> = == ~ = | Z lewej na prawą |
Równość | == ~ = | Z lewej na prawą |
Logiczne AND | i | Z lewej na prawą |
Logiczne LUB | lub | Z lewej na prawą |
Może zaistnieć sytuacja, w której trzeba będzie kilkakrotnie wykonać blok kodu. Ogólnie instrukcje są wykonywane sekwencyjnie: pierwsza instrukcja funkcji jest wykonywana jako pierwsza, po niej następuje druga i tak dalej.
Języki programowania zapewniają różne struktury kontrolne, które pozwalają na bardziej skomplikowane ścieżki wykonywania.
Instrukcja pętli umożliwia wielokrotne wykonanie instrukcji lub grupy instrukcji. Poniżej przedstawiono ogólną formę instrukcji pętli w większości języków programowania -
Lua zapewnia następujące typy pętli do obsługi wymagań dotyczących pętli.
Sr.No. | Typ i opis pętli |
---|---|
1 | pętla while Powtarza instrukcję lub grupę instrukcji, gdy dany warunek jest prawdziwy. Testuje warunek przed wykonaniem treści pętli. |
2 | dla pętli Wykonuje sekwencję instrukcji wiele razy i skraca kod zarządzający zmienną pętli. |
3 | powtarzaj ... aż do pętli Powtarza operację grupy instrukcji aż do spełnienia warunku do momentu. |
4 | pętle zagnieżdżone Możesz użyć jednej lub więcej pętli wewnątrz dowolnej innej pętli while, for lub do..while . |
Instrukcja kontroli pętli
Instrukcja sterowania pętlą zmienia wykonanie z jego normalnej sekwencji. Gdy wykonanie opuszcza zakres, wszystkie automatyczne obiekty utworzone w tym zakresie są niszczone.
Lua obsługuje następujące instrukcje sterujące.
Sr.No. | Oświadczenie i opis kontroli |
---|---|
1 | instrukcja break Kończy loop i przekazuje wykonanie do instrukcji bezpośrednio po pętli lub przełączniku. |
Nieskończona pętla
Pętla staje się nieskończoną pętlą, jeśli warunek nigdy nie staje się fałszywy. PlikwhileW tym celu często używana jest pętla. Ponieważ warunek podajemy bezpośrednio jako prawdziwy, jest on wykonywany na zawsze. Aby przerwać tę pętlę, możemy użyć instrukcji break.
while( true )
do
print("This loop will run forever.")
end
Struktury decyzyjne wymagają, aby programista określił jeden lub więcej warunków, które mają być ocenione lub przetestowane przez program, wraz z instrukcją lub instrukcjami do wykonania, jeśli warunek zostanie określony jako prawdziwy, i opcjonalnie inne instrukcje do wykonania, jeśli warunek jest określany jako fałszywy.
Poniżej przedstawiono ogólną formę typowej struktury podejmowania decyzji występującej w większości języków programowania -
Język programowania Lua zakłada dowolną kombinację wartości logicznych true i non-nil wartości jako truei jeśli jest to wartość logiczna false lub nil, to przyjmuje się, że falsewartość. Należy zauważyć, że w Luazero will be considered as true.
Język programowania Lua zapewnia następujące typy oświadczeń decyzyjnych.
Sr.No. | Oświadczenie i opis |
---|---|
1 | jeśli oświadczenie Jeśli oświadczenie składa się z logicznej wypowiedzi, a następnie przez jeden lub więcej instrukcji. |
2 | if ... else oświadczenie Po instrukcji if może następować opcjonalna instrukcja else , która jest wykonywana, gdy wyrażenie boolowskie ma wartość false. |
3 | zagnieżdżone instrukcje if Możesz użyć jednej instrukcji if lub else if wewnątrz innej instrukcji if lub else if . |
A function is a group of statements that together perform a task. You can divide up your code into separate functions. How you divide up your code among different functions is up to you, but logically the division usually unique, is so each function performs a specific task.
The Lua language provides numerous built-in methods that your program can call. For example, method print() to print the argument passed as input in console.
A function is known with various names like a method or a sub-routine or a procedure etc.
Defining a Function
The general form of a method definition in Lua programming language is as follows −
optional_function_scope function function_name( argument1, argument2, argument3........,
argumentn)
function_body
return result_params_comma_separated
end
A method definition in Lua programming language consists of a method header and a method body. Here are all the parts of a method −
Optional Function Scope − You can use keyword local to limit the scope of the function or ignore the scope section, which will make it a global function.
Function Name − This is the actual name of the function. The function name and the parameter list together constitute the function signature.
Arguments − An argument is like a placeholder. When a function is invoked, you pass a value to the argument. This value is referred to as the actual parameter or argument. The parameter list refers to the type, order, and number of the arguments of a method. Arguments are optional; that is, a method may contain no argument.
Function Body − The method body contains a collection of statements that define what the method does.
Return − In Lua, it is possible to return multiple values by following the return keyword with the comma separated return values.
Example
Following is the source code for a function called max(). This function takes two parameters num1 and num2 and returns the maximum between the two −
--[[ function returning the max between two numbers --]]
function max(num1, num2)
if (num1 > num2) then
result = num1;
else
result = num2;
end
return result;
end
Function Arguments
If a function is to use arguments, it must declare the variables that accept the values of the arguments. These variables are called the formal parameters of the function.
The formal parameters behave like other local variables inside the function and are created upon entry into the function and destroyed upon exit.
Calling a Function
While creating a Lua function, you give a definition of what the function has to do. To use a method, you will have to call that function to perform the defined task.
When a program calls a function, program control is transferred to the called function. A called function performs the defined task and when its return statement is executed or when its function's end is reached, it returns program control back to the main program.
To call a method, you simply need to pass the required parameters along with the method name and if the method returns a value, then you can store the returned value. For example −
function max(num1, num2)
if (num1 > num2) then
result = num1;
else
result = num2;
end
return result;
end
-- calling a function
print("The maximum of the two numbers is ",max(10,4))
print("The maximum of the two numbers is ",max(5,6))
When we run the above code, we will get the following output.
The maximum of the two numbers is 10
The maximum of the two numbers is 6
Assigning and Passing Functions
In Lua, we can assign the function to variables and also can pass them as parameters of another function. Here is a simple example for assigning and passing a function as parameter in Lua.
myprint = function(param)
print("This is my print function - ##",param,"##")
end
function add(num1,num2,functionPrint)
result = num1 + num2
functionPrint(result)
end
myprint(10)
add(2,5,myprint)
When we run the above code, we will get the following output.
This is my print function - ## 10 ##
This is my print function - ## 7 ##
Function with Variable Argument
It is possible to create functions with variable arguments in Lua using '...' as its parameter. We can get a grasp of this by seeing an example in which the function will return the average and it can take variable arguments.
function average(...)
result = 0
local arg = {...}
for i,v in ipairs(arg) do
result = result + v
end
return result/#arg
end
print("The average is",average(10,5,3,4,5,6))
When we run the above code, we will get the following output.
The average is 5.5
String is a sequence of characters as well as control characters like form feed. String can be initialized with three forms which includes −
- Characters between single quotes
- Characters between double quotes
- Characters between [[ and ]]
An example for the above three forms are shown below.
string1 = "Lua"
print("\"String 1 is\"",string1)
string2 = 'Tutorial'
print("String 2 is",string2)
string3 = [["Lua Tutorial"]]
print("String 3 is",string3)
When we run the above program, we will get the following output.
"String 1 is" Lua
String 2 is Tutorial
String 3 is "Lua Tutorial"
Escape sequence characters are used in string to change the normal interpretation of characters. For example, to print double inverted commas (""), we have used \" in the above example. The escape sequence and its use is listed below in the table.
Escape Sequence | Use |
---|---|
\a | Bell |
\b | Backspace |
\f | Formfeed |
\n | New line |
\r | Carriage return |
\t | Tab |
\v | Vertical tab |
\\ | Backslash |
\" | Double quotes |
\' | Single quotes |
\[ | Left square bracket |
\] | Right square bracket |
String Manipulation
Lua supports string to manipulate strings −
Sr.No. | Method & Purpose |
---|---|
1 | string.upper(argument) Returns a capitalized representation of the argument. |
2 | string.lower(argument) Returns a lower case representation of the argument. |
3 | string.gsub(mainString,findString,replaceString) Returns a string by replacing occurrences of findString with replaceString. |
4 | string.find(mainString,findString, optionalStartIndex,optionalEndIndex) Returns the start index and end index of the findString in the main string and nil if not found. |
5 | string.reverse(arg) Returns a string by reversing the characters of the passed string. |
6 | string.format(...) Returns a formatted string. |
7 | string.char(arg) and string.byte(arg) Returns internal numeric and character representations of input argument. |
8 | string.len(arg) Returns a length of the passed string. |
9 | string.rep(string, n)) Returns a string by repeating the same string n number times. |
10 | .. Thus operator concatenates two strings. |
Now, let's dive into a few examples to exactly see how these string manipulation functions behave.
Case Manipulation
A sample code for manipulating the strings to upper and lower case is given below.
string1 = "Lua";
print(string.upper(string1))
print(string.lower(string1))
When we run the above program, we will get the following output.
LUA
lua
Replacing a Substring
A sample code for replacing occurrences of one string with another is given below.
string = "Lua Tutorial"
-- replacing strings
newstring = string.gsub(string,"Tutorial","Language")
print("The new string is "..newstring)
When we run the above program, we will get the following output.
The new string is Lua Language
Finding and Reversing
A sample code for finding the index of substring and reversing string is given below.
string = "Lua Tutorial"
-- replacing strings
print(string.find(string,"Tutorial"))
reversedString = string.reverse(string)
print("The new string is",reversedString)
When we run the above program, we will get the following output.
5 12
The new string is lairotuT auL
Formatting Strings
Many times in our programming, we may need to print strings in a formatted way. You can use the string.format function to format the output as shown below.
string1 = "Lua"
string2 = "Tutorial"
number1 = 10
number2 = 20
-- Basic string formatting
print(string.format("Basic formatting %s %s",string1,string2))
-- Date formatting
date = 2; month = 1; year = 2014
print(string.format("Date formatting %02d/%02d/%03d", date, month, year))
-- Decimal formatting
print(string.format("%.4f",1/3))
When we run the above program, we will get the following output.
Basic formatting Lua Tutorial
Date formatting 02/01/2014
0.3333
Character and Byte Representations
A sample code for character and byte representation, which is used for converting the string from string to internal representation and vice versa.
-- Byte conversion
-- First character
print(string.byte("Lua"))
-- Third character
print(string.byte("Lua",3))
-- first character from last
print(string.byte("Lua",-1))
-- Second character
print(string.byte("Lua",2))
-- Second character from last
print(string.byte("Lua",-2))
-- Internal Numeric ASCII Conversion
print(string.char(97))
When we run the above program, we will get the following output.
76
97
97
117
117
a
Other Common Functions
The common string manipulations include string concatenation, finding length of string and at times repeating the same string multiple times. The example for these operations is given below.
string1 = "Lua"
string2 = "Tutorial"
-- String Concatenations using ..
print("Concatenated string",string1..string2)
-- Length of string
print("Length of string1 is ",string.len(string1))
-- Repeating strings
repeatedString = string.rep(string1,3)
print(repeatedString)
When we run the above program, we will get the following output.
Concatenated string LuaTutorial
Length of string1 is 3
LuaLuaLua
Arrays are ordered arrangement of objects, which may be a one-dimensional array containing a collection of rows or a multi-dimensional array containing multiple rows and columns.
In Lua, arrays are implemented using indexing tables with integers. The size of an array is not fixed and it can grow based on our requirements, subject to memory constraints.
One-Dimensional Array
A one-dimensional array can be represented using a simple table structure and can be initialized and read using a simple for loop. An example is shown below.
array = {"Lua", "Tutorial"}
for i = 0, 2 do
print(array[i])
end
When we run the above code, we wil get the following output.
nil
Lua
Tutorial
As you can see in the above code, when we are trying to access an element in an index that is not there in the array, it returns nil. In Lua, indexing generally starts at index 1. But it is possible to create objects at index 0 and below 0 as well. Array using negative indices is shown below where we initialize the array using a for loop.
array = {}
for i= -2, 2 do
array[i] = i *2
end
for i = -2,2 do
print(array[i])
end
When we run the above code, we will get the following output.
-4
-2
0
2
4
Multi-Dimensional Array
Multi-dimensional arrays can be implemented in two ways.
- Array of arrays
- Single dimensional array by manipulating indices
An example for multidimensional array of 3. 3 is shown below using array of arrays.
-- Initializing the array
array = {}
for i=1,3 do
array[i] = {}
for j=1,3 do
array[i][j] = i*j
end
end
-- Accessing the array
for i=1,3 do
for j=1,3 do
print(array[i][j])
end
end
When we run the above code, we will get the following output.
1
2
3
2
4
6
3
6
9
An example for multidimensional array is shown below using manipulating indices.
-- Initializing the array
array = {}
maxRows = 3
maxColumns = 3
for row=1,maxRows do
for col=1,maxColumns do
array[row*maxColumns +col] = row*col
end
end
-- Accessing the array
for row=1,maxRows do
for col=1,maxColumns do
print(array[row*maxColumns +col])
end
end
When we run the above code, we will get the following output.
1
2
3
2
4
6
3
6
9
As you can see in the above example, data is stored based on indices. It is possible to place the elements in a sparse way and it is the way Lua implementation of a matrix works. Since it does not store nil values in Lua, it is possible to save lots of memory without any special technique in Lua as compared to special techniques used in other programming languages.
Iterator is a construct that enables you to traverse through the elements of the so called collection or container. In Lua, these collections often refer to tables, which are used to create various data structures like array.
Generic For Iterator
A generic for iterator provides the key value pairs of each element in the collection. A simple example is given below.
array = {"Lua", "Tutorial"}
for key,value in ipairs(array)
do
print(key, value)
end
When we run the above code, we will get the following output −
1 Lua
2 Tutorial
The above example uses the default ipairs iterator function provided by Lua.
In Lua we use functions to represent iterators. Based on the state maintenance in these iterator functions, we have two main types −
- Stateless Iterators
- Stateful Iterators
Stateless Iterators
By the name itself we can understand that this type of iterator function does not retain any state.
Let us now see an example of creating our own iterator using a simple function that prints the squares of n numbers.
function square(iteratorMaxCount,currentNumber)
if currentNumber<iteratorMaxCount
then
currentNumber = currentNumber+1
return currentNumber, currentNumber*currentNumber
end
end
for i,n in square,3,0
do
print(i,n)
end
When we run the above program, we will get the following output.
1 1
2 4
3 9
The above code can be modified slightly to mimic the way ipairs function of iterators work. It is shown below.
function square(iteratorMaxCount,currentNumber)
if currentNumber<iteratorMaxCount
then
currentNumber = currentNumber+1
return currentNumber, currentNumber*currentNumber
end
end
function squares(iteratorMaxCount)
return square,iteratorMaxCount,0
end
for i,n in squares(3)
do
print(i,n)
end
When we run the above program, we will get the following output.
1 1
2 4
3 9
Stateful Iterators
The previous example of iteration using function does not retain the state. Each time the function is called, it returns the next element of the collection based on a second variable sent to the function. To hold the state of the current element, closures are used. Closure retain variables values across functions calls. To create a new closure, we create two functions including the closure itself and a factory, the function that creates the closure.
Let us now see an example of creating our own iterator in which we will be using closures.
array = {"Lua", "Tutorial"}
function elementIterator (collection)
local index = 0
local count = #collection
-- The closure function is returned
return function ()
index = index + 1
if index <= count
then
-- return the current element of the iterator
return collection[index]
end
end
end
for element in elementIterator(array)
do
print(element)
end
When we run the above program, we will get the following output.
Lua
Tutorial
In the above example, we can see that elementIterator has another method inside that uses the local external variables index and count to return each of the element in the collection by incrementing the index each time the function is called.
We can create our own function iterators using closure as shown above and it can return multiple elements for each of the time we iterate through the collection.
Introduction
Tables are the only data structure available in Lua that helps us create different types like arrays and dictionaries. Lua uses associative arrays and which can be indexed with not only numbers but also with strings except nil. Tables have no fixed size and can grow based on our need.
Lua uses tables in all representations including representation of packages. When we access a method string.format, it means, we are accessing the format function available in the string package.
Representation and Usage
Tables are called objects and they are neither values nor variables. Lua uses a constructor expression {} to create an empty table. It is to be known that there is no fixed relationship between a variable that holds reference of table and the table itself.
--sample table initialization
mytable = {}
--simple table value assignment
mytable[1]= "Lua"
--removing reference
mytable = nil
-- lua garbage collection will take care of releasing memory
When we have a table a with set of elements and if we assign it to b, both a and b refer to the same memory. No separate memory is allocated separately for b. When a is set to nil, table will be still accessible to b. When there are no reference to a table, then garbage collection in Lua takes care of cleaning up process to make these unreferenced memory to be reused again.
An example is shown below for explaining the above mentioned features of tables.
-- Simple empty table
mytable = {}
print("Type of mytable is ",type(mytable))
mytable[1]= "Lua"
mytable["wow"] = "Tutorial"
print("mytable Element at index 1 is ", mytable[1])
print("mytable Element at index wow is ", mytable["wow"])
-- alternatetable and mytable refers to same table
alternatetable = mytable
print("alternatetable Element at index 1 is ", alternatetable[1])
print("alternatetable Element at index wow is ", alternatetable["wow"])
alternatetable["wow"] = "I changed it"
print("mytable Element at index wow is ", mytable["wow"])
-- only variable released and and not table
alternatetable = nil
print("alternatetable is ", alternatetable)
-- mytable is still accessible
print("mytable Element at index wow is ", mytable["wow"])
mytable = nil
print("mytable is ", mytable)
Po uruchomieniu powyższego programu otrzymamy następujący wynik -
Type of mytable is table
mytable Element at index 1 is Lua
mytable Element at index wow is Tutorial
alternatetable Element at index 1 is Lua
alternatetable Element at index wow is Tutorial
mytable Element at index wow is I changed it
alternatetable is nil
mytable Element at index wow is I changed it
mytable is nil
Manipulacja tabelą
Istnieją wbudowane funkcje do manipulacji tabelą i są one wymienione w poniższej tabeli.
Sr.No. | Metoda i cel |
---|---|
1 | table.concat (table [, sep [, i [, j]]]) Łączy ciągi w tabelach na podstawie podanych parametrów. Zobacz przykład po szczegóły. |
2 | table.insert (table, [pos,] value) Wstawia wartość do tabeli w określonej pozycji. |
3 | table.maxn (table) Zwraca największy indeks liczbowy. |
4 | table.remove (table [, pos]) Usuwa wartość z tabeli. |
5 | table.sort (table [, comp]) Sortuje tabelę na podstawie opcjonalnego argumentu komparatora. |
Zobaczmy kilka przykładów powyższych funkcji.
Łączenie tabel
Możemy użyć funkcji concat, aby połączyć dwie tabele, jak pokazano poniżej -
fruits = {"banana","orange","apple"}
-- returns concatenated string of table
print("Concatenated string ",table.concat(fruits))
--concatenate with a character
print("Concatenated string ",table.concat(fruits,", "))
--concatenate fruits based on index
print("Concatenated string ",table.concat(fruits,", ", 2,3))
Po uruchomieniu powyższego programu otrzymamy następujący wynik -
Concatenated string bananaorangeapple
Concatenated string banana, orange, apple
Concatenated string orange, apple
Wstaw i usuń
Wstawianie i wyjmowanie elementów w tabelach jest najczęściej spotykane podczas manipulacji tabelami. Jest to wyjaśnione poniżej.
fruits = {"banana","orange","apple"}
-- insert a fruit at the end
table.insert(fruits,"mango")
print("Fruit at index 4 is ",fruits[4])
--insert fruit at index 2
table.insert(fruits,2,"grapes")
print("Fruit at index 2 is ",fruits[2])
print("The maximum elements in table is",table.maxn(fruits))
print("The last element is",fruits[5])
table.remove(fruits)
print("The previous last element is",fruits[5])
Po uruchomieniu powyższego programu otrzymamy następujące dane wyjściowe -
Fruit at index 4 is mango
Fruit at index 2 is grapes
The maximum elements in table is 5
The last element is mango
The previous last element is nil
Sortowanie tabel
Często wymagamy sortowania tabeli w określonej kolejności. Funkcje sortowania sortują elementy w tabeli alfabetycznie. Przykład tego pokazano poniżej.
fruits = {"banana","orange","apple","grapes"}
for k,v in ipairs(fruits) do
print(k,v)
end
table.sort(fruits)
print("sorted table")
for k,v in ipairs(fruits) do
print(k,v)
end
Po uruchomieniu powyższego programu otrzymamy następujący wynik -
1 banana
2 orange
3 apple
4 grapes
sorted table
1 apple
2 banana
3 grapes
4 orange
Co to jest moduł?
Moduł jest jak biblioteka, którą można załadować za pomocą require i ma jedną globalną nazwę zawierającą tabelę. Ten moduł może składać się z wielu funkcji i zmiennych. Wszystkie te funkcje i zmienne są umieszczane w tabeli, która działa jak przestrzeń nazw. Ponadto dobrze zachowujący się moduł ma niezbędne zabezpieczenia, aby zwrócić tę tabelę na żądanie.
Specjalność modułów Lua
Użycie tabel w modułach pomaga nam na wiele sposobów i umożliwia nam manipulowanie modułami w taki sam sposób, w jaki manipulujemy każdą inną tabelą Lua. W wyniku możliwości manipulowania modułami zapewnia dodatkowe funkcje, dla których inne języki wymagają specjalnych mechanizmów. Dzięki temu swobodnemu mechanizmowi modułów w Lua, użytkownik może wywoływać funkcje w Lua na wiele sposobów. Kilka z nich pokazano poniżej.
-- Assuming we have a module printFormatter
-- Also printFormatter has a funtion simpleFormat(arg)
-- Method 1
require "printFormatter"
printFormatter.simpleFormat("test")
-- Method 2
local formatter = require "printFormatter"
formatter.simpleFormat("test")
-- Method 3
require "printFormatter"
local formatterFunction = printFormatter.simpleFormat
formatterFunction("test")
W powyższym przykładowym kodzie możesz zobaczyć, jak elastyczne jest programowanie w Lua, bez specjalnego dodatkowego kodu.
Wymagana funkcja
Lua dostarczyła funkcję wysokiego poziomu o nazwie require, aby załadować wszystkie niezbędne moduły. Jest to tak proste, jak to tylko możliwe, aby uniknąć zbyt dużej ilości informacji o module, aby go załadować. Funkcja require zakłada po prostu, że moduły są fragmentem kodu, który definiuje pewne wartości, które w rzeczywistości są funkcjami lub tabelami zawierającymi funkcje.
Przykład
Rozważmy prosty przykład, w którym jedna funkcja ma funkcje matematyczne. Nazwijmy ten moduł mymath, a nazwa pliku to mymath.lua. Zawartość pliku jest następująca -
local mymath = {}
function mymath.add(a,b)
print(a+b)
end
function mymath.sub(a,b)
print(a-b)
end
function mymath.mul(a,b)
print(a*b)
end
function mymath.div(a,b)
print(a/b)
end
return mymath
Teraz, aby uzyskać dostęp do tego modułu Lua w innym pliku, powiedzmy moduletutorial.lua, musisz użyć następującego segmentu kodu.
mymathmodule = require("mymath")
mymathmodule.add(10,20)
mymathmodule.sub(30,20)
mymathmodule.mul(10,20)
mymathmodule.div(30,20)
Aby uruchomić ten kod, musimy umieścić dwa pliki Lua w tym samym katalogu lub alternatywnie możesz umieścić plik modułu w ścieżce pakietu i wymaga dodatkowej konfiguracji. Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
30
10
200
1.5
Rzeczy do zapamiętania
Umieść zarówno moduły, jak i uruchamiany plik w tym samym katalogu.
Nazwa modułu i jego nazwa pliku powinny być takie same.
Najlepszą praktyką jest zwracanie modułów dla funkcji wymagającej, dlatego moduł powinien być najlepiej zaimplementowany, jak pokazano powyżej, chociaż można znaleźć inne typy implementacji w innym miejscu.
Stary sposób implementacji modułów
Pozwólcie, że przepiszę ten sam przykład w starszy sposób, który wykorzystuje typ implementacji package.seeall. Było to używane w Lua w wersjach 5.1 i 5.0. Moduł mymath pokazano poniżej.
module("mymath", package.seeall)
function mymath.add(a,b)
print(a+b)
end
function mymath.sub(a,b)
print(a-b)
end
function mymath.mul(a,b)
print(a*b)
end
function mymath.div(a,b)
print(a/b)
end
Wykorzystanie modułów w moduletutorial.lua pokazano poniżej.
require("mymath")
mymath.add(10,20)
mymath.sub(30,20)
mymath.mul(10,20)
mymath.div(30,20)
Po uruchomieniu powyższego uzyskamy ten sam wynik. Zaleca się jednak używanie starszej wersji kodu i zakłada się, że jest ona mniej bezpieczna. Wiele zestawów SDK, które używają Lua do programowania, takich jak Corona SDK, wycofało użycie tego.
Metatabela to tabela, która pomaga w modyfikowaniu zachowania tabeli, do której jest dołączona, za pomocą zestawu kluczy i powiązanych meta metod. Te metody meta to potężna funkcjonalność Lua, która umożliwia takie funkcje, jak -
Zmiana / dodawanie funkcjonalności do operatorów na tabelach.
Wyszukiwanie metadanych, gdy klucz nie jest dostępny w tabeli przy użyciu __index w metatable.
Istnieją dwie ważne metody, które są używane do obsługi metatartów, które obejmują:
setmetatable(table,metatable) - Ta metoda służy do ustawiania metatabeli dla tabeli.
getmetatable(table) - Ta metoda jest używana do uzyskania metatable tabeli.
Najpierw przyjrzyjmy się, jak ustawić jedną tabelę jako metatable innej. Jest to pokazane poniżej.
mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)
Powyższy kod można przedstawić w jednej linii, jak pokazano poniżej.
mytable = setmetatable({},{})
_indeks
Prosty przykład metatabeli do wyszukiwania metatabeli, gdy nie jest ona dostępna w tabeli, pokazano poniżej.
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return mytable[key]
end
end
})
print(mytable.key1,mytable.key2)
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
value1 metatablevalue
Wyjaśnijmy krokami, co się stało w powyższym przykładzie.
Tabela mytable tutaj jest {key1 = "value1"}.
Metatable jest ustawiane dla mytable, który zawiera funkcję dla __index, którą nazywamy metametodą.
Metametoda wykonuje proste zadanie wyszukania indeksu „klucz2”, jeśli zostanie znaleziony, zwraca „metatablevalue”, w przeciwnym razie zwraca wartość mytable dla odpowiedniego indeksu.
Możemy mieć uproszczoną wersję powyższego programu, jak pokazano poniżej.
mytable = setmetatable({key1 = "value1"},
{ __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)
__newindex
Kiedy dodamy __newindex do metatable, jeśli klucze nie są dostępne w tabeli, zachowanie nowych kluczy zostanie zdefiniowane za pomocą metod meta. Prosty przykład, w którym indeks metatabeli jest ustawiany, gdy indeks nie jest dostępny w głównej tabeli, podano poniżej.
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "new value 1"
print(mytable.key1,mymetatable.newkey1)
Po uruchomieniu powyższego programu otrzymasz następujące dane wyjściowe.
value1
nil new value 2
new value 1 nil
Możesz zobaczyć w powyższym programie, jeśli klucz istnieje w głównej tabeli, po prostu go aktualizuje. Kiedy klucz nie jest dostępny w utrzymywanym, dodaje ten klucz do metatable.
Inny przykład, który aktualizuje tę samą tabelę za pomocą funkcji rawset, pokazano poniżej.
mytable = setmetatable({key1 = "value1"}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, "\""..value.."\"")
end
})
mytable.key1 = "new value"
mytable.key2 = 4
print(mytable.key1,mytable.key2)
Po uruchomieniu powyższego programu otrzymamy następujący wynik.
new value "4"
rawset ustawia wartość bez użycia __newindex metatabli. Podobnie istnieje rawget, który pobiera wartość bez użycia __index.
Dodawanie zachowania operatora do tabel
Prosty przykład połączenia dwóch tabel za pomocą operatora + pokazano poniżej -
mytable = setmetatable({ 1, 2, 3 }, {
__add = function(mytable, newtable)
for i = 1, table.maxn(newtable) do
table.insert(mytable, table.maxn(mytable)+1,newtable[i])
end
return mytable
end
})
secondtable = {4,5,6}
mytable = mytable + secondtable
for k,v in ipairs(mytable) do
print(k,v)
end
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
1 1
2 2
3 3
4 4
5 5
6 6
Klucz __add jest zawarty w metatabeli, aby dodać zachowanie operatora +. Tabela kluczy i odpowiadających im operatorów jest pokazana poniżej.
Sr.No. | Tryb i opis |
---|---|
1 | __add Zmienia zachowanie operatora „+”. |
2 | __sub Zmienia zachowanie operatora „-”. |
3 | __mul Zmienia zachowanie operatora „*”. |
4 | __div Zmienia zachowanie operatora „/”. |
5 | __mod Zmienia zachowanie operatora „%”. |
6 | __unm Zmienia zachowanie operatora „-”. |
7 | __concat Zmienia zachowanie operatora „..”. |
8 | __eq Zmienia zachowanie operatora „==”. |
9 | __lt Zmienia zachowanie operatora „<”. |
10 | __le Zmienia zachowanie operatora „<=”. |
__połączenie
Dodanie zachowania wywołania metody odbywa się za pomocą instrukcji __call. Prosty przykład, który zwraca sumę wartości w głównej tabeli z przekazaną tabelą.
mytable = setmetatable({10}, {
__call = function(mytable, newtable)
sum = 0
for i = 1, table.maxn(mytable) do
sum = sum + mytable[i]
end
for i = 1, table.maxn(newtable) do
sum = sum + newtable[i]
end
return sum
end
})
newtable = {10,20,30}
print(mytable(newtable))
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
70
__tostring
Aby zmienić zachowanie instrukcji print, możemy użyć metametody __tostring. Poniżej przedstawiono prosty przykład.
mytable = setmetatable({ 10, 20, 30 }, {
__tostring = function(mytable)
sum = 0
for k, v in pairs(mytable) do
sum = sum + v
end
return "The sum of values in the table is " .. sum
end
})
print(mytable)
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
The sum of values in the table is 60
Jeśli w pełni znasz możliwości metatabeli, możesz naprawdę wykonać wiele operacji, które byłyby bardzo złożone bez jej używania. Spróbuj więc bardziej popracować nad używaniem metatabel z różnymi opcjami dostępnymi w metatabelach, jak wyjaśniono w przykładach, a także utwórz własne próbki.
Wprowadzenie
Programy mają charakter współpracy, co pozwala na wykonanie dwóch lub więcej metod w sposób kontrolowany. W przypadku koreprogramów w danym momencie działa tylko jeden program, a ten działający program zawiesza wykonywanie tylko wtedy, gdy wyraźnie zażąda zawieszenia.
Powyższa definicja może wydawać się niejasna. Załóżmy, że mamy dwie metody, jedną główną metodę programu i korektę. Kiedy wywołujemy program za pomocą funkcji resume, zaczyna się on wykonywać, a kiedy wywołujemy funkcję yield, wstrzymuje wykonywanie. Ponownie ten sam program może kontynuować wykonywanie z innym wywołaniem funkcji wznawiania, z którego został zawieszony. Ten proces może trwać do końca wykonywania programu.
Funkcje dostępne w programach Coroutines
W poniższej tabeli wymieniono wszystkie dostępne funkcje programów w Lua i ich zastosowanie.
Sr.No. | Metoda i cel |
---|---|
1 | coroutine.create (f) Tworzy nowy program z funkcją fi zwraca obiekt typu „thread”. |
2 | coroutine.resume (co [, val1, ...]) Wznawia współpracę z coroutine i przekazuje parametry, jeśli takie istnieją. Zwraca stan operacji i opcjonalne inne zwracane wartości. |
3 | coroutine.running () Zwraca działający coroutine lub nil, jeśli jest wywoływany w głównym wątku. |
4 | coroutine.status (co) Zwraca jedną z wartości z uruchomionego, normalnego, zawieszonego lub martwego na podstawie stanu programu. |
5 | coroutine.wrap (f) Podobnie jak coroutine.create, funkcja coroutine.wrap również tworzy coroutine, ale zamiast zwracać sam coroutine, zwraca funkcję, która po wywołaniu wznawia proces. |
6 | coroutine.yield (...) Zawiesza uruchomiony program. Parametr przekazany do tej metody działa jako dodatkowe wartości zwracane do funkcji wznawiania. |
Przykład
Spójrzmy na przykład, aby zrozumieć koncepcję programów.
co = coroutine.create(function (value1,value2)
local tempvar3 = 10
print("coroutine section 1", value1, value2, tempvar3)
local tempvar1 = coroutine.yield(value1+1,value2+1)
tempvar3 = tempvar3 + value1
print("coroutine section 2",tempvar1 ,tempvar2, tempvar3)
local tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2)
tempvar3 = tempvar3 + value1
print("coroutine section 3",tempvar1,tempvar2, tempvar3)
return value2, "end"
end)
print("main", coroutine.resume(co, 3, 2))
print("main", coroutine.resume(co, 12,14))
print("main", coroutine.resume(co, 5, 6))
print("main", coroutine.resume(co, 10, 20))
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
coroutine section 1 3 2 10
main true 4 3
coroutine section 2 12 nil 13
main true 5 1
coroutine section 3 5 6 16
main true 2 end
main false cannot resume dead coroutine
Co robi powyższy przykład?
Jak wspomniano wcześniej, używamy funkcji wznawiania, aby rozpocząć operację, i funkcji uzyskiwania, aby ją zatrzymać. Możesz również zobaczyć, że istnieje wiele wartości zwracanych przez funkcję wznowienia programu coroutine.
Najpierw tworzymy program i przypisujemy go do zmiennej o nazwie co, a program przyjmuje dwie zmienne jako parametry.
Kiedy wywołujemy pierwszą funkcję wznawiania, wartości 3 i 2 są zachowywane w zmiennych tymczasowych wartość1 i wartość2 do końca procedury.
Aby to zrozumieć, użyliśmy tempvar3, który początkowo ma wartość 10 i jest aktualizowany do 13 i 16 przez kolejne wywołania programów, ponieważ wartość 1 jest zachowywana jako 3 przez cały czas wykonywania coroutine.
Pierwszy plik coroutine.yield zwraca dwie wartości 4 i 3 do funkcji resume, którą otrzymujemy, aktualizując parametry wejściowe 3 i 2 w instrukcji yield. Otrzymuje również status prawda / fałsz wykonania rutynowego.
Inną rzeczą związaną z coroutines jest to, w jaki sposób obsługiwane są kolejne parametry wywołania wznowienia, w powyższym przykładzie; widać, że zmienna coroutine.yield otrzymuje parametry następnego wywołania, co zapewnia potężny sposób wykonywania nowej operacji z zachowaniem istniejących wartości parametrów.
Wreszcie, gdy wszystkie instrukcje w procedurach zostaną wykonane, kolejne wywołania będą zwracać jako odpowiedź fałszywe i „nie można wznowić martwego programu”.
Kolejny przykład programu
Spójrzmy na prosty program, który zwraca liczbę od 1 do 5 za pomocą funkcji yield i funkcji wznowienia. Tworzy program, jeśli nie jest dostępny, lub wznawia istniejący program.
function getNumber()
local function getNumberHelper()
co = coroutine.create(function ()
coroutine.yield(1)
coroutine.yield(2)
coroutine.yield(3)
coroutine.yield(4)
coroutine.yield(5)
end)
return co
end
if(numberHelper) then
status, number = coroutine.resume(numberHelper);
if coroutine.status(numberHelper) == "dead" then
numberHelper = getNumberHelper()
status, number = coroutine.resume(numberHelper);
end
return number
else
numberHelper = getNumberHelper()
status, number = coroutine.resume(numberHelper);
return number
end
end
for index = 1, 10 do
print(index, getNumber())
end
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
1 1
2 2
3 3
4 4
5 5
6 1
7 2
8 3
9 4
10 5
Często występuje porównanie koreprogramów z wątkami języków wieloprogramowych, ale musimy zrozumieć, że programy te mają podobne cechy wątku, ale wykonują się tylko pojedynczo i nigdy nie są wykonywane jednocześnie.
Kontrolujemy kolejność wykonywania programu, aby sprostać potrzebom, zapewniając tymczasowe zachowanie pewnych informacji. Używanie zmiennych globalnych z programami zapewnia jeszcze większą elastyczność programom.
Biblioteka I / O służy do czytania i manipulowania plikami w Lua. W Lua istnieją dwa rodzaje operacji na plikach, mianowicie niejawne deskryptory plików i jawne deskryptory plików.
W poniższych przykładach użyjemy przykładowego pliku test.lua, jak pokazano poniżej.
-- sample test.lua
-- sample2 test.lua
Prosta operacja otwierania pliku wykorzystuje następującą instrukcję.
file = io.open (filename [, mode])
W poniższej tabeli przedstawiono różne tryby plików.
Sr.No. | Tryb i opis |
---|---|
1 | "r" Tryb tylko do odczytu i jest to domyślny tryb, w którym otwierany jest istniejący plik. |
2 | "w" Tryb umożliwiający zapis, który zastępuje istniejący plik lub tworzy nowy plik. |
3 | "a" Tryb dołączania, który otwiera istniejący plik lub tworzy nowy plik do dołączenia. |
4 | "r+" Tryb odczytu i zapisu dla istniejącego pliku. |
5 | "w+" Wszystkie istniejące dane są usuwane, jeśli plik istnieje lub zostanie utworzony nowy plik z uprawnieniami do odczytu i zapisu. |
6 | "a+" Tryb dołączania z włączonym trybem odczytu, który otwiera istniejący plik lub tworzy nowy plik. |
Niejawne deskryptory plików
Niejawne deskryptory plików używają standardowych trybów wejścia / wyjścia lub używają jednego pliku wejściowego i jednego pliku wyjściowego. Przykład użycia niejawnych deskryptorów plików przedstawiono poniżej.
-- Opens a file in read
file = io.open("test.lua", "r")
-- sets the default input file as test.lua
io.input(file)
-- prints the first line of the file
print(io.read())
-- closes the open file
io.close(file)
-- Opens a file in append mode
file = io.open("test.lua", "a")
-- sets the default output file as test.lua
io.output(file)
-- appends a word test to the last line of the file
io.write("-- End of the test.lua file")
-- closes the open file
io.close(file)
Po uruchomieniu programu otrzymasz wynik z pierwszej linii pliku test.lua. W przypadku naszego programu otrzymaliśmy następujący wynik.
-- Sample test.lua
To był dla nas pierwszy wiersz instrukcji w pliku test.lua. Również wiersz „- End of the test.lua file” zostałby dołączony do ostatniej linii kodu test.lua.
W powyższym przykładzie można zobaczyć, jak niejawne deskryptory współpracują z systemem plików przy użyciu metod io. "X". Powyższy przykład używa io.read () bez opcjonalnego parametru. Opcjonalnym parametrem może być dowolny z poniższych.
Sr.No. | Tryb i opis |
---|---|
1 | "*n" Odczytuje od bieżącej pozycji pliku i zwraca liczbę, jeśli istnieje na tej pozycji lub zwraca nil. |
2 | "*a" Zwraca całą zawartość pliku z bieżącej pozycji pliku. |
3 | "*l" Odczytuje wiersz z bieżącej pozycji pliku i przenosi pozycję pliku do następnego wiersza. |
4 | number Odczytuje liczbę bajtów określoną w funkcji. |
Inne popularne metody I / O obejmują:
io.tmpfile() - Zwraca plik tymczasowy do odczytu i zapisu, który zostanie usunięty po zamknięciu programu.
io.type(file) - Zwraca czy plik, plik zamknięty czy nil na podstawie pliku wejściowego.
io.flush() - Czyści domyślny bufor wyjściowy.
io.lines(optional file name)- Zapewnia ogólny iterator pętli for, który przechodzi przez plik i zamyka plik na końcu, w przypadku podania nazwy pliku lub użycia pliku domyślnego, który nie jest zamknięty na końcu pętli.
Jawne deskryptory plików
Często używamy jawnego deskryptora pliku, który pozwala nam manipulować wieloma plikami jednocześnie. Te funkcje są dość podobne do niejawnych deskryptorów plików. Tutaj używamy file: function_name zamiast io.function_name. Poniższy przykład wersji pliku tego samego niejawnego przykładu deskryptorów plików jest pokazany poniżej.
-- Opens a file in read mode
file = io.open("test.lua", "r")
-- prints the first line of the file
print(file:read())
-- closes the opened file
file:close()
-- Opens a file in append mode
file = io.open("test.lua", "a")
-- appends a word test to the last line of the file
file:write("--test")
-- closes the open file
file:close()
Po uruchomieniu programu uzyskasz podobne dane wyjściowe, co przykład niejawnych deskryptorów.
-- Sample test.lua
Wszystkie tryby otwierania plików i parametrów do odczytu dla zewnętrznych deskryptorów są takie same, jak niejawne deskryptory plików.
Inne popularne metody plików obejmują:
file:seek(optional whence, optional offset)- Kiedy parametr jest ustawiony na „set”, „cur” lub „end”. Ustawia nowy wskaźnik pliku ze zaktualizowaną pozycją pliku od początku pliku. W tej funkcji przesunięcia są liczone od zera. Przesunięcie jest mierzone od początku pliku, jeśli pierwszy argument to „set”; od bieżącej pozycji w pliku, jeśli jest "aktualna"; lub od końca pliku, jeśli to „koniec”. Domyślne wartości argumentów to „cur” i 0, więc bieżącą pozycję pliku można uzyskać, wywołując tę funkcję bez argumentów.
file:flush() - Czyści domyślny bufor wyjściowy.
io.lines(optional file name)- Zapewnia ogólny iterator pętli for, który przechodzi przez plik i zamyka plik na końcu, w przypadku podania nazwy pliku lub użycia pliku domyślnego, który nie jest zamknięty na końcu pętli.
Przykład użycia metody wyszukiwania pokazano poniżej. Przesuwa kursor z 25 pozycji przed końcem pliku. Funkcja odczytu wypisuje pozostałą część pliku z pozycji wyszukiwania.
-- Opens a file in read
file = io.open("test.lua", "r")
file:seek("end",-25)
print(file:read("*a"))
-- closes the opened file
file:close()
Otrzymasz wyniki podobne do poniższych.
sample2 test.lua
--test
Możesz bawić się wszystkimi różnymi trybami i parametrami, aby poznać pełną zdolność operacji na plikach Lua.
Potrzeba obsługi błędów
Obsługa błędów jest dość krytyczna, ponieważ operacje w świecie rzeczywistym często wymagają użycia złożonych operacji, które obejmują operacje na plikach, transakcje w bazie danych i wywołania usług internetowych.
W każdym programowaniu zawsze wymagana jest obsługa błędów. Błędy mogą być dwojakiego rodzaju, w tym:
- Błędy składniowe
- Błędy czasu wykonywania
Błędy składniowe
Błędy składniowe występują z powodu niewłaściwego użycia różnych składników programu, takich jak operatory i wyrażenia. Poniżej przedstawiono prosty przykład błędu składniowego.
a == 2
Jak wiesz, istnieje różnica między używaniem pojedynczego „równego” i podwójnego „równego”. Używanie jednego zamiast drugiego może prowadzić do błędu. Jedno „równe” odnosi się do przypisania, a podwójne „równe” odnosi się do porównania. Podobnie mamy wyrażenia i funkcje, które mają predefiniowane sposoby implementacji.
Kolejny przykład błędu składniowego pokazano poniżej -
for a= 1,10
print(a)
end
Po uruchomieniu powyższego programu otrzymamy następujące dane wyjściowe -
lua: test2.lua:2: 'do' expected near 'print'
Błędy składniowe są znacznie łatwiejsze w obsłudze niż błędy czasu wykonania, ponieważ interpreter Lua lokalizuje błąd wyraźniej niż w przypadku błędu wykonania. Z powyższego błędu, możemy łatwo wiedzieć, że dodanie zrób oświadczenia przed instrukcja print jest wymagane zgodnie strukturze Lua.
Błędy czasu wykonywania
W przypadku błędów w czasie wykonywania program wykonuje się pomyślnie, ale może to skutkować błędami w czasie wykonywania z powodu błędów w danych wejściowych lub nieprawidłowej obsługi funkcji. Poniżej przedstawiono prosty przykład pokazujący błąd czasu wykonywania.
function add(a,b)
return a+b
end
add(10)
Kiedy budujemy program, będzie się on budował i działał. Po uruchomieniu wyświetla błąd czasu wykonywania.
lua: test2.lua:2: attempt to perform arithmetic on local 'b' (a nil value)
stack traceback:
test2.lua:2: in function 'add'
test2.lua:5: in main chunk
[C]: ?
Jest to błąd w czasie wykonywania, który wystąpił z powodu nieprzekazywania dwóch zmiennych. Plikb jest oczekiwany i tutaj jest zerowy i powoduje błąd.
Funkcje asertu i błędu
Aby poradzić sobie z błędami, często używamy dwóch funkcji - assert i error. Poniżej przedstawiono prosty przykład.
local function add(a,b)
assert(type(a) == "number", "a is not a number")
assert(type(b) == "number", "b is not a number")
return a+b
end
add(10)
Kiedy uruchomimy powyższy program, otrzymamy następujące wyjście błędu.
lua: test2.lua:3: b is not a number
stack traceback:
[C]: in function 'assert'
test2.lua:3: in function 'add'
test2.lua:6: in main chunk
[C]: ?
Plik error (message [, level])kończy ostatnią wywołaną funkcję chronioną i zwraca komunikat jako komunikat o błędzie. Ten błąd funkcji nigdy nie powraca. Zwykle komunikat o błędzie dodaje pewne informacje o pozycji błędu na początku wiadomości. Argument poziomu określa, jak uzyskać pozycję błędu. Przy poziomie 1 (domyślnym) pozycja błędu jest miejscem wywołania funkcji błędu. Poziom 2 wskazuje błąd w miejscu wywołania funkcji, która wywołała błąd; i tak dalej. Przekazanie poziomu 0 pozwala uniknąć dodania do komunikatu informacji o pozycji błędu.
pcall i xpcall
W programowaniu Lua, aby uniknąć wyrzucania tych błędów i obsługi błędów, musimy użyć funkcji pcall lub xpcall.
Plik pcall (f, arg1, ...)function wywołuje żądaną funkcję w trybie chronionym. Jeśli jakiś błąd wystąpi w funkcji f, nie zgłasza błędu. Po prostu zwraca stan błędu. Poniżej przedstawiono prosty przykład użycia pcall.
function myfunction ()
n = n/nil
end
if pcall(myfunction) then
print("Success")
else
print("Failure")
end
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
Failure
Plik xpcall (f, err)funkcja wywołuje żądaną funkcję, a także ustawia procedurę obsługi błędów. Żaden błąd wewnątrz f nie jest propagowany; zamiast tego xpcall wychwytuje błąd, wywołuje funkcję err z oryginalnym obiektem błędu i zwraca kod stanu.
Poniżej przedstawiono prosty przykład dla xpcall.
function myfunction ()
n = n/nil
end
function myerrorhandler( err )
print( "ERROR:", err )
end
status = xpcall( myfunction, myerrorhandler )
print( status)
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
ERROR: test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value)
false
Jako programista najważniejsze jest, aby zadbać o właściwą obsługę błędów w programach, które piszesz. Korzystanie z obsługi błędów może zapewnić obsługę nieoczekiwanych warunków wykraczających poza warunki brzegowe bez przeszkadzania użytkownikowi programu.
Lua udostępnia bibliotekę debugowania, która zapewnia wszystkie prymitywne funkcje potrzebne do stworzenia własnego debugera. Mimo że nie ma wbudowanego debuggera Lua, mamy wiele debuggerów dla Lua, stworzonych przez różnych programistów, z których wielu jest open source.
Funkcje dostępne w bibliotece debugowania Lua są wymienione w poniższej tabeli wraz z ich zastosowaniami.
Sr.No. | Metoda i cel |
---|---|
1 | debug() Wchodzi w tryb interaktywny do debugowania, który pozostaje aktywny, dopóki nie wpiszemy tylko cont w linii i nie naciśniemy enter. Użytkownik może przeglądać zmienne w tym trybie za pomocą innych funkcji. |
2 | getfenv(object) Zwraca środowisko obiektu. |
3 | gethook(optional thread) Zwraca bieżące ustawienia zaczepienia wątku jako trzy wartości - bieżącą funkcję zaczepienia, bieżącą maskę zaczepienia i bieżącą liczbę zaczepów. |
4 | getinfo(optional thread, function or stack level, optional flag) Zwraca tabelę z informacjami o funkcji. Możesz podać funkcję bezpośrednio lub możesz podać liczbę jako wartość funkcji, co oznacza, że funkcja działa na poziomie funkcja stosu wywołań danego wątku - poziom 0 jest bieżącą funkcją (samo getinfo); poziom 1 to funkcja, która wywołuje getinfo; i tak dalej. Jeśli funkcja jest liczbą większą niż liczba aktywnych funkcji, to getinfo zwraca nil. |
5 | getlocal(optional thread, stack level, local index) Zwraca nazwę i wartość zmiennej lokalnej z indeksem lokalnym funkcji na poziomie stosu. Zwraca nil, jeśli nie ma zmiennej lokalnej o podanym indeksie i zgłasza błąd, gdy jest wywoływana z poziomem spoza zakresu. |
6 | getmetatable(value) Zwraca metatabelę danego obiektu lub nil, jeśli nie ma metatablicy. |
7 | getregistry() Zwraca tabelę rejestru, wstępnie zdefiniowaną tabelę, której może użyć dowolny kod C do przechowywania dowolnej wartości Lua, którą musi przechowywać. |
8 | getupvalue(function, upvalue index) Ta funkcja zwraca nazwę i wartość upvalue z indeksem w górę funkcji func. Funkcja zwraca nil, jeśli nie ma upvalue o podanym indeksie. |
9 | setfenv(function or thread or userdata, environment table) Ustawia środowisko danego obiektu na podaną tabelę. Zwraca obiekt. |
10 | sethook(optional thread, hook function, hook mask string with "c" and/or "r" and/or "l", optional instruction count) Ustawia daną funkcję jako punkt zaczepienia. Maska ciągów i liczba liczb określają, kiedy zostanie wywołany hak. Tutaj c, r i l są wywoływane za każdym razem, gdy Lua wywołuje, zwraca i wprowadza odpowiednio każdy wiersz kodu w funkcji. |
11 | setlocal(optional thread, stack level, local index, value) Przypisuje wartość do zmiennej lokalnej z indeksem lokalnym funkcji na poziomie stosu. Funkcja zwraca nil, jeśli nie ma zmiennej lokalnej o podanym indeksie, i wywołuje błąd, gdy jest wywoływana z poziomem spoza zakresu. W przeciwnym razie zwraca nazwę zmiennej lokalnej. |
12 | setmetatable(value, metatable) Ustawia metatabelę dla danego obiektu na podaną tabelę (która może być zerowa). |
13 | setupvalue(function, upvalue index, value) Ta funkcja przypisuje wartość do upvalue z indeksem w górę funkcji func. Funkcja zwraca nil, jeśli nie ma upvalue o podanym indeksie. W przeciwnym razie zwraca nazwę upvalue. |
14 | traceback(optional thread, optional message string, optional level argument) Tworzy rozszerzony komunikat o błędzie ze śledzeniem wstecznym. |
Powyższa lista jest pełną listą funkcji debugowania w Lua i często używamy biblioteki, która używa powyższych funkcji i zapewnia łatwiejsze debugowanie. Korzystanie z tych funkcji i tworzenie własnego debuggera jest dość skomplikowane i nie jest preferowane. W każdym razie zobaczymy przykład prostego użycia funkcji debugowania.
function myfunction ()
print(debug.traceback("Stack trace"))
print(debug.getinfo(1))
print("Stack trace end")
return 10
end
myfunction ()
print(debug.getinfo(1))
Kiedy uruchomimy powyższy program, otrzymamy ślad stosu, jak pokazano poniżej.
Stack trace
stack traceback:
test2.lua:2: in function 'myfunction'
test2.lua:8: in main chunk
[C]: ?
table: 0054C6C8
Stack trace end
W powyższym programie przykładowym ślad stosu jest drukowany przy użyciu funkcji debug.trace dostępnej w bibliotece debugowania. Plik debug.getinfo pobiera aktualną tabelę funkcji.
Debugowanie - przykład
Często potrzebujemy znać lokalne zmienne funkcji do debugowania. W tym celu możemy użyć getupvalue, a do ustawienia tych zmiennych lokalnych - setupvalue. Poniżej przedstawiono prosty przykład.
function newCounter ()
local n = 0
local k = 0
return function ()
k = n
n = n + 1
return n
end
end
counter = newCounter ()
print(counter())
print(counter())
local i = 1
repeat
name, val = debug.getupvalue(counter, i)
if name then
print ("index", i, name, "=", val)
if(name == "n") then
debug.setupvalue (counter,2,10)
end
i = i + 1
end -- if
until not name
print(counter())
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
1
2
index 1 k = 1
index 2 n = 2
11
W tym przykładzie licznik aktualizuje się o jeden po każdym wywołaniu. Aktualny stan zmiennej lokalnej możemy zobaczyć za pomocą funkcji getupvalue. Następnie ustawiamy zmienną lokalną na nową wartość. Tutaj n wynosi 2 przed wywołaniem operacji set. Używając funkcji setupvalue, jest aktualizowana do 10. Teraz, gdy wywołujemy funkcję licznika, zwróci ona 11 zamiast 3.
Typy debugowania
- Debugowanie wiersza poleceń
- Graficzne debugowanie
Debugowanie wiersza poleceń
Debugowanie w wierszu poleceń to rodzaj debugowania, który wykorzystuje wiersz poleceń do debugowania za pomocą poleceń i instrukcji drukowania. Istnieje wiele debuggerów wiersza poleceń dostępnych dla Lua, z których kilka jest wymienionych poniżej.
RemDebug- RemDebug to zdalny debugger dla Lua 5.0 i 5.1. Pozwala zdalnie sterować wykonywaniem innego programu Lua, ustawiać punkty przerwania i sprawdzać aktualny stan programu. RemDebug może również debugować skrypty CGILua.
clidebugger- Prosty debugger interfejsu wiersza poleceń dla Lua 5.1 napisany w czystym Lua. Nie jest zależny od niczego innego niż standardowe biblioteki Lua 5.1. Został zainspirowany RemDebug, ale nie ma swoich zdalnych obiektów.
ctrace - Narzędzie do śledzenia wywołań Lua API.
xdbLua - Prosty debugger wiersza poleceń Lua dla platformy Windows.
LuaInterface - Debugger- Ten projekt jest rozszerzeniem debuggera dla LuaInterface. Podnosi wbudowany interfejs debugowania Lua na wyższy poziom. Interakcja z debugerem odbywa się za pomocą zdarzeń i wywołań metod.
Rldb- To jest zdalny debugger Lua przez gniazdo, dostępny zarówno w systemie Windows, jak i Linux. Zapewnia znacznie więcej funkcji niż jakikolwiek istniejący.
ModDebug - Pozwala to na zdalne sterowanie wykonaniem innego programu Lua, ustawianie punktów przerwania i sprawdzanie aktualnego stanu programu.
Graficzne debugowanie
Debugowanie graficzne jest dostępne za pomocą IDE, w którym zapewnia się wizualne debugowanie różnych stanów, takich jak wartości zmiennych, ślady stosu i inne powiązane informacje. Istnieje wizualna reprezentacja i kontrola wykonania krok po kroku za pomocą punktów przerwania, przechodzenia do, przechodzenia i innych przycisków w IDE.
Istnieje wiele graficznych debuggerów dla Lua i zawiera następujące.
SciTE - Domyślne środowisko IDE systemu Windows dla Lua zapewnia wiele funkcji debugowania, takich jak punkty przerwania, krok, krok, krok po kroku, obserwowanie zmiennych i tak dalej.
Decoda - To jest graficzny debugger z obsługą zdalnego debugowania.
ZeroBrane Studio- Lua IDE ze zintegrowanym zdalnym debugerem, widokiem stosu, widokiem zegarka, zdalną konsolą, analizatorem statycznym i nie tylko. Działa z silnikami LuaJIT, Love2d, Moai i innymi silnikami Lua; Windows, OSX i Linux. Otwarte źródło.
akdebugger - Wtyczka debuggera i edytora Lua dla Eclipse.
luaedit - Obejmuje zdalne debugowanie, debugowanie lokalne, podświetlanie składni, listę propozycji ukończenia, silnik propozycji parametrów, zaawansowane zarządzanie punktami przerwania (w tym system warunków na punktach przerwania i liczbę trafień), listę funkcji, listę zmiennych globalnych i lokalnych, zegarki, zarządzanie zorientowane na rozwiązania.
Lua korzysta z automatycznego zarządzania pamięcią, które wykorzystuje czyszczenie pamięci w oparciu o określone algorytmy wbudowane w Lua. W wyniku automatycznego zarządzania pamięcią jako programista -
- Nie musisz martwić się o przydzielanie pamięci dla obiektów.
- Nie musisz ich uwalniać, gdy nie są już potrzebne, z wyjątkiem ustawienia go na zero.
Lua używa garbage collectora, który działa od czasu do czasu do zbierania martwych obiektów, gdy nie są już dostępne z programu Lua.
Wszystkie obiekty, w tym tabele, dane użytkownika, funkcje, wątek, ciąg itd., Podlegają automatycznemu zarządzaniu pamięcią. Lua używa przyrostowego zbieracza znaczników i wymiatania, który używa dwóch liczb do kontrolowania cykli czyszczenia pamięci, a mianowiciegarbage collector pause i garbage collector step multiplier. Te wartości są w procentach, a wartość 100 jest często równa 1 wewnętrznie.
Wstrzymanie odśmiecania pamięci
Pauza modułu odśmiecania pamięci jest używana do kontrolowania, jak długo musi on czekać, zanim; jest ponownie wywoływany przez automatyczne zarządzanie pamięcią Lua. Wartości mniejsze niż 100 oznaczałyby, że Lua nie będzie czekać na następny cykl. Podobnie, wyższe wartości tej wartości spowodowałyby, że odśmiecacz byłby powolny i mniej agresywny z natury. Wartość 200 oznacza, że kolektor czeka, aż całkowita ilość używanej pamięci podwoi się przed rozpoczęciem nowego cyklu. W związku z tym, w zależności od charakteru i szybkości aplikacji, może zaistnieć potrzeba zmiany tej wartości, aby uzyskać najlepszą wydajność w aplikacjach Lua.
Mnożnik kroku garbage collectora
Ten mnożnik kroku kontroluje względną prędkość garbage collectora względem alokacji pamięci w programie Lua. Większe wartości kroków spowodują, że moduł odśmiecania pamięci będzie bardziej agresywny, a także zwiększy rozmiar kroku każdego przyrostowego kroku czyszczenia pamięci. Wartości mniejsze niż 100 mogą często prowadzić do tego, że moduł odśmiecający nie dokończy swojego cyklu i nie jest to ogólnie preferowane. Wartość domyślna to 200, co oznacza, że moduł odśmiecania pamięci działa dwa razy szybciej niż alokacja pamięci.
Funkcje garbage collectora
Jako programiści mamy pewną kontrolę nad automatycznym zarządzaniem pamięcią w Lua. W tym celu mamy następujące metody.
collectgarbage("collect") - Uruchamia jeden pełny cykl czyszczenia pamięci.
collectgarbage("count") - Zwraca ilość pamięci aktualnie używanej przez program w kilobajtach.
collectgarbage("restart") - Jeśli odśmiecacz został zatrzymany, uruchamia go ponownie.
collectgarbage("setpause")- Ustawia wartość podaną jako drugi parametr podzieloną przez 100 na zmienną pauzy modułu odśmiecania pamięci. Jego zastosowania są omówione nieco powyżej.
collectgarbage("setstepmul")- Ustawia wartość podaną jako drugi parametr podzieloną przez 100 na zmienną mnożnika kroku śmieci. Jego zastosowania są omówione nieco powyżej.
collectgarbage("step")- Uruchamia jeden krok czyszczenia pamięci. Im większy jest drugi argument, tym większy będzie ten krok. Kolekcjonowanie zwróci wartość true, jeśli wyzwalany krok był ostatnim krokiem cyklu czyszczenia pamięci.
collectgarbage("stop") - Zatrzymuje odśmiecacz, jeśli jest uruchomiony.
Poniżej przedstawiono prosty przykład wykorzystujący przykład garbage collectora.
mytable = {"apple", "orange", "banana"}
print(collectgarbage("count"))
mytable = nil
print(collectgarbage("count"))
print(collectgarbage("collect"))
print(collectgarbage("count"))
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe. Należy pamiętać, że ten wynik będzie się różnić ze względu na różnicę w typie systemu operacyjnego, a także funkcję automatycznego zarządzania pamięcią w Lua.
23.1455078125 149
23.2880859375 295
0
22.37109375 380
W powyższym programie widać, że po zakończeniu czyszczenia pamięci zmniejszyło się zużycie pamięci. Ale nie jest to obowiązkowe. Nawet jeśli ich nie wywołamy, zostanie to wykonane automatycznie na późniejszym etapie przez interpreter Lua po zdefiniowanym okresie.
Oczywiście w razie potrzeby możemy zmienić zachowanie garbage collectora za pomocą tych funkcji. Funkcje te zapewniają programiście dodatkowe możliwości obsługi złożonych sytuacji. W zależności od typu pamięci wymaganej przez program możesz korzystać z tej funkcji lub nie. Ale bardzo przydatne jest poznanie użycia pamięci w aplikacjach i sprawdzenie go podczas samego programowania, aby uniknąć niepożądanych skutków po wdrożeniu.
Wprowadzenie do OOP
Programowanie obiektowe (OOP) to jedna z najczęściej używanych technik programowania, która jest używana we współczesnej erze programowania. Istnieje wiele języków programowania obsługujących OOP, które obejmują:
- C++
- Java
- Objective-C
- Smalltalk
- C#
- Ruby
Funkcje OOP
Class - Klasa to rozszerzalny szablon do tworzenia obiektów, zapewniający początkowe wartości stanu (zmienne składowe) i implementacje zachowania.
Objects - Jest instancją klasy i ma przydzieloną dla siebie oddzielną pamięć.
Inheritance - Jest to koncepcja, dzięki której zmienne i funkcje jednej klasy są dziedziczone przez inną klasę.
Encapsulation- Jest to proces łączenia danych i funkcji wewnątrz klasy. Dostęp do danych można uzyskać poza klasą za pomocą funkcji. Nazywa się to również abstrakcją danych.
OOP w Lua
Możesz zaimplementować obiektową orientację w Lua za pomocą tabel i funkcji pierwszej klasy Lua. Po umieszczeniu funkcji i powiązanych danych w tabeli tworzony jest obiekt. Dziedziczenie można zaimplementować za pomocą metatabli, udostępniając mechanizm wyszukiwania dla nieistniejących funkcji (metod) i pól w obiektach nadrzędnych.
Tabele w Lua mają cechy obiektu, takie jak stan i tożsamość, które są niezależne od jego wartości. Dwa obiekty (tabele) o tej samej wartości to różne obiekty, podczas gdy obiekt może mieć różne wartości w różnym czasie, ale zawsze jest to ten sam obiekt. Podobnie jak obiekty, tabele mają cykl życia, który jest niezależny od tego, kto je stworzył lub gdzie zostały utworzone.
Przykład z prawdziwego świata
Pojęcie orientacji obiektowej jest szeroko stosowane, ale aby uzyskać właściwe i maksymalne korzyści, należy je dokładnie zrozumieć.
Rozważmy prosty przykład matematyczny. Często spotykamy się z sytuacjami, w których pracujemy nad różnymi kształtami, takimi jak koło, prostokąt i kwadrat.
Kształty mogą mieć wspólną właściwość Area. Zatem możemy rozszerzyć inne kształty z podstawowego kształtu obiektu o wspólny obszar właściwości. Każdy z kształtów może mieć swoje własne właściwości, a funkcje, takie jak prostokąt, mogą mieć właściwości długość, szerokość, obszar jako jego właściwości oraz printArea i ObliczArea jako jego funkcje.
Tworzenie prostej klasy
Poniżej przedstawiono prostą implementację klasy dla prostokąta z trzema właściwościami: obszar, długość i szerokość. Posiada również funkcję printArea do drukowania obliczonego obszaru.
-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}
-- Derived class method new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
-- Derived class method printArea
function Rectangle:printArea ()
print("The area of Rectangle is ",self.area)
end
Tworzenie obiektu
Tworzenie obiektu to proces przydzielania pamięci dla instancji klasy. Każdy z obiektów ma własną pamięć i ma wspólne dane klasowe.
r = Rectangle:new(nil,10,20)
Dostęp do właściwości
Możemy uzyskać dostęp do właściwości w klasie za pomocą operatora kropki, jak pokazano poniżej -
print(r.length)
Dostęp do funkcji członka
Możesz uzyskać dostęp do funkcji składowej za pomocą operatora dwukropka z obiektem, jak pokazano poniżej -
r:printArea()
Pamięć zostaje przydzielona i ustawiane są wartości początkowe. Proces inicjalizacji można porównać z konstruktorami w innych językach obiektowych. To nic innego jak funkcja, która umożliwia ustawienie wartości, jak pokazano powyżej.
Kompletny przykład
Przyjrzyjmy się kompletnemu przykładowi użycia orientacji obiektowej w Lua.
-- Meta class
Shape = {area = 0}
-- Base class method new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- Base class method printArea
function Shape:printArea ()
print("The area is ",self.area)
end
-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()
Po uruchomieniu powyższego programu otrzymasz następujące dane wyjściowe.
The area is 100
Dziedziczenie w Lua
Dziedziczenie to proces rozszerzania prostych obiektów podstawowych, takich jak kształt, na prostokąty, kwadraty i tak dalej. Jest często używany w świecie rzeczywistym do udostępniania i rozszerzania podstawowych właściwości i funkcji.
Zobaczmy proste rozszerzenie klasy. Mamy klasę, jak pokazano poniżej.
-- Meta class
Shape = {area = 0}
-- Base class method new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- Base class method printArea
function Shape:printArea ()
print("The area is ",self.area)
end
Możemy rozszerzyć kształt do klasy kwadratowej, jak pokazano poniżej.
Square = Shape:new()
-- Derived class method new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
Podstawowe funkcje bazowe
Możemy przesłonić funkcje klasy bazowej, czyli zamiast używać funkcji w klasie bazowej, klasa pochodna może mieć własną implementację, jak pokazano poniżej -
-- Derived class method printArea
function Square:printArea ()
print("The area of square is ",self.area)
end
Przykład pełnego dziedziczenia
Możemy rozszerzyć prostą implementację klasy w Lua, jak pokazano powyżej, za pomocą innej nowej metody z pomocą metatabel. Wszystkie zmienne składowe i funkcje klasy bazowej są zachowywane w klasie pochodnej.
-- Meta class
Shape = {area = 0}
-- Base class method new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- Base class method printArea
function Shape:printArea ()
print("The area is ",self.area)
end
-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()
Square = Shape:new()
-- Derived class method new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
-- Derived class method printArea
function Square:printArea ()
print("The area of square is ",self.area)
end
-- Creating an object
mysquare = Square:new(nil,10)
mysquare:printArea()
Rectangle = Shape:new()
-- Derived class method new
function Rectangle:new (o,length,breadth)
o = o or Shape:new(o)
setmetatable(o, self)
self.__index = self
self.area = length * breadth
return o
end
-- Derived class method printArea
function Rectangle:printArea ()
print("The area of Rectangle is ",self.area)
end
-- Creating an object
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()
Po uruchomieniu powyższego programu otrzymamy następujące dane wyjściowe -
The area is 100
The area of square is 100
The area of Rectangle is 200
W powyższym przykładzie utworzyliśmy dwie klasy pochodne - Rectangle i Square z klasy bazowej Square. Istnieje możliwość przesłonięcia funkcji klasy bazowej w klasie pochodnej. W tym przykładzie klasa pochodna przesłania funkcję printArea.
Lua to bardzo elastyczny język i jest często używany na wielu platformach, w tym w aplikacjach internetowych. Społeczność Kepler, która została utworzona w 2004 roku w celu dostarczania komponentów internetowych typu open source w Lua.
Chociaż istnieją inne frameworki internetowe wykorzystujące Lua, które zostały opracowane, skupimy się głównie na komponentach dostarczonych przez społeczność Kepler.
Aplikacje i ramy
Orbit to framework sieciowy MVC dla Lua, oparty na WSAPI.
WSAPI jest interfejsem API, który oddziela serwer hosta sieci Web od aplikacji internetowych Lua i jest podstawą wielu projektów.
Xavante to serwer WWW Lua, który oferuje interfejs WSAPI.
Sputnik to wiki / CMS opracowane przez WSAPI w Kepler Project, używane do humoru i rozrywki.
CGILuaoferuje tworzenie stron internetowych LuaPages i LuaScripts w oparciu o WSAPI, ale nie jest już obsługiwane. Zamiast tego użyj Orbit, Sputnik lub WSAPI.
W tym samouczku postaramy się, abyś zrozumiał, co może zrobić Lua i aby dowiedzieć się więcej o jego instalacji i użytkowaniu, polecam keplerowi stronę
Orbita
Orbit to platforma internetowa MVC dla Lua. Całkowicie rezygnuje z modelu „skryptów” CGILua na rzecz aplikacji, w których każda aplikacja Orbit może zmieścić się w jednym pliku, ale jeśli chcesz, możesz podzielić ją na wiele plików.
Wszystkie aplikacje Orbit są zgodne z protokołem WSAPI, więc obecnie współpracują z Xavante, CGI i Fastcgi. Zawiera program uruchamiający, który ułatwia uruchamianie instancji Xavante w celu rozwoju.
Najłatwiejszym sposobem zainstalowania Orbit jest użycie LuaRocks. Luarocks install orbit to polecenie instalacji. W tym celu musisz najpierw zainstalować LuaRocks .
Jeśli nie zainstalowałeś wszystkich zależności, oto kroki, które należy wykonać, aby skonfigurować Orbit w środowisku Unix / Linux.
Instalowanie Apache
Połącz się ze swoim serwerem. Zainstaluj Apache2, jego moduły pomocnicze i włącz wymagane moduły Apache2 za pomocą -
$ sudo apt-get install apache2 libapache2-mod-fcgid libfcgi-dev build-essential $ sudo a2enmod rewrite
$ sudo a2enmod fcgid $ sudo /etc/init.d/apache2 force-reload
Zainstaluj LuaRocks
$ sudo apt-get install luarocks
Zainstaluj WSAPI, FCGI, Orbit i Xavante
$ sudo luarocks install orbit
$ sudo luarocks install wsapi-xavante $ sudo luarocks install wsapi-fcgi
Konfigurowanie Apache2
$ sudo raj /etc/apache2/sites-available/default
Dodaj tę sekcję poniżej sekcji <Directory / var / www /> pliku konfiguracyjnego. Jeśli w tej sekcji znajduje się „AllowOverride None”, należy zmienić „None” na „All”, aby plik .htaccess mógł lokalnie zastąpić konfigurację.
<IfModule mod_fcgid.c>
AddHandler fcgid-script .lua
AddHandler fcgid-script .ws
AddHandler fcgid-script .op
FCGIWrapper "/usr/local/bin/wsapi.fcgi" .ws
FCGIWrapper "/usr/local/bin/wsapi.fcgi" .lua
FCGIWrapper "/usr/local/bin/op.fcgi" .op
#FCGIServer "/usr/local/bin/wsapi.fcgi" -idle-timeout 60 -processes 1
#IdleTimeout 60
#ProcessLifeTime 60
</IfModule>
Zrestartuj serwer, aby upewnić się, że wprowadzone zmiany zostały wprowadzone.
Aby włączyć swoją aplikację, musisz dodać + ExecCGI do pliku .htaccess w katalogu głównym aplikacji Orbit - w tym przypadku / var / www.
Options +ExecCGI
DirectoryIndex index.ws
Prosty przykład - orbita
#!/usr/bin/env index.lua
-- index.lua
require"orbit"
-- declaration
module("myorbit", package.seeall, orbit.new)
-- handler
function index(web)
return my_home_page()
end
-- dispatch
myorbit:dispatch_get(index, "/", "/index")
-- Sample page
function my_home_page()
return [[
<head></head>
<html>
<h2>First Page</h2>
</html>
]]
end
Teraz powinieneś móc uruchomić przeglądarkę internetową. Idź do http: // localhost: 8080 / i powinieneś zobaczyć następujące dane wyjściowe -
First Page
Orbit udostępnia inną opcję, tj. Kod Lua może generować HTML.
#!/usr/bin/env index.lua
-- index.lua
require"orbit"
function generate()
return html {
head{title "HTML Example"},
body{
h2{"Here we go again!"}
}
}
end
orbit.htmlify(generate)
print(generate())
Tworzenie formularzy
Poniżej przedstawiono prosty przykład formularza -
#!/usr/bin/env index.lua
require"orbit"
function wrap (inner)
return html{ head(), body(inner) }
end
function test ()
return wrap(form (H'table' {
tr{td"First name",td( input{type = 'text', name='first'})},
tr{td"Second name",td(input{type = 'text', name='second'})},
tr{ td(input{type = 'submit', value = 'Submit!'}),
td(input{type = 'submit',value = 'Cancel'})
},
}))
end
orbit.htmlify(wrap,test)
print(test())
WSAPI
Jak wspomniano wcześniej, WSAPI działa jako baza dla wielu projektów i ma wiele wbudowanych funkcji. Możesz używać WSAPI i obsługiwać następujące platformy,
- Windows
- Systemy oparte na UNIX
Obsługiwane serwery i interfejsy przez WSAPI obejmują,
- CGI
- FastCGI
- Xavante
WSAPI udostępnia szereg bibliotek, co ułatwia nam programowanie w sieci przy użyciu Lua. Niektóre z obsługiwanych funkcji w Lua obejmują:
- Przetwarzanie żądania
- Buforowanie wyjściowe
- Authentication
- Przesyłanie plików
- Poproś o izolację
- Multiplexing
Poniżej przedstawiono prosty przykład WSAPI -
#!/usr/bin/env wsapi.cgi
module(..., package.seeall)
function run(wsapi_env)
local headers = { ["Content-type"] = "text/html" }
local function hello_text()
coroutine.yield("<html><body>")
coroutine.yield("<p>Hello Wsapi!</p>")
coroutine.yield("<p>PATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>")
coroutine.yield("<p>SCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>")
coroutine.yield("</body></html>")
end
return 200, headers, coroutine.wrap(hello_text)
end
Możesz zobaczyć w powyższym kodzie, że tworzona i zwracana jest prosta strona HTML. Możesz zobaczyć użycie coroutines, które umożliwiają zwracanie instrukcji po instrukcji do funkcji wywołującej. Na koniec zwracany jest kod statusu html (200), nagłówki i strona html.
Xavante
Xavante to serwer WWW Lua HTTP 1.1, który wykorzystuje architekturę modułową opartą na programach obsługi mapowanych na URI. Xavante obecnie oferuje,
- Obsługa plików
- Moduł obsługi przekierowań
- Program obsługi WSAPI
Obsługa plików jest używana dla plików ogólnych. Moduł obsługi przekierowań umożliwia ponowne mapowanie URI i obsługę WSAPI do obsługi aplikacji WSAPI.
Poniżej przedstawiono prosty przykład.
require "xavante.filehandler"
require "xavante.cgiluahandler"
require "xavante.redirecthandler"
-- Define here where Xavante HTTP documents scripts are located
local webDir = XAVANTE_WEB
local simplerules = {
{ -- URI remapping example
match = "^[^%./]*/$",
with = xavante.redirecthandler,
params = {"index.lp"}
},
{ -- cgiluahandler example
match = {"%.lp$", "%.lp/.*$", "%.lua$", "%.lua/.*$" },
with = xavante.cgiluahandler.makeHandler (webDir)
},
{ -- filehandler example
match = ".",
with = xavante.filehandler,
params = {baseDir = webDir}
},
}
xavante.HTTP{
server = {host = "*", port = 8080},
defaultHost = {
rules = simplerules
},
}
Aby używać wirtualnych hostów z Xavante, wywołanie xavante.HTTP zostanie zmienione na coś takiego:
xavante.HTTP{
server = {host = "*", port = 8080},
defaultHost = {},
virtualhosts = {
["www.sitename.com"] = simplerules
}
}
Lua Web Components
Copas, dyspozytor oparty na programach, które mogą być używane przez serwery TCP / IP.
Cosmo, mechanizm „bezpiecznych szablonów”, który chroni Twoją aplikację przed dowolnym kodem w szablonach.
Coxpcall hermetyzuje natywne lua pcall i xpcall z kompatybilnymi z coroutine.
LuaFileSystem, przenośny sposób dostępu do podstawowej struktury katalogów i atrybutów plików.
Rings, biblioteka, która umożliwia tworzenie nowych stanów Lua z poziomu Lua.
Uwaga końcowa
Jest tak wiele dostępnych dla nas frameworków internetowych i komponentów opartych na Lua i w zależności od potrzeb, można je wybrać. Dostępne są inne frameworki internetowe, które obejmują:
Moonstalkumożliwia wydajne tworzenie i hosting dynamicznie generowanych projektów internetowych zbudowanych w języku Lua; od podstawowych stron po złożone aplikacje.
Lapis, framework do tworzenia aplikacji internetowych przy użyciu MoonScript (lub Lua), który działa w dostosowanej wersji Nginx o nazwie OpenResty.
Lua Server Pages, wtyczka do silnika skryptów Lua, która odrzuca wszelkie inne podejście do wbudowanego tworzenia stron internetowych, oferuje radykalne skróty do tradycyjnych stron serwera C.
Te platformy internetowe mogą wykorzystywać aplikacje internetowe i pomagać w wykonywaniu zaawansowanych operacji.
W przypadku prostych operacji na danych możemy używać plików, ale czasami te operacje na plikach mogą nie być wydajne, skalowalne i wydajne. W tym celu często możemy przejść na korzystanie z baz danych. LuaSQL to prosty interfejs od Lua do wielu systemów zarządzania bazami danych. LuaSQL to biblioteka, która zapewnia obsługę różnych typów SQL. Obejmuje to:
- SQLite
- Mysql
- ODBC
W tym samouczku zajmiemy się obsługą baz danych MySQL i SQLite w Lua. Używa to ogólnego interfejsu dla obu i powinno być możliwe przeniesienie tej implementacji również do innych typów baz danych. Najpierw zobaczmy, jak możesz wykonywać operacje w MySQL.
Konfiguracja bazy MySQL
Aby poniższe przykłady działały zgodnie z oczekiwaniami, potrzebujemy początkowej konfiguracji bazy danych. Założenia są wymienione poniżej.
Zainstalowałeś i skonfigurowałeś MySQL z domyślnym użytkownikiem jako root i hasłem jako '123456'.
Utworzyłeś test bazy danych.
Przeszedłeś przez samouczek MySQL, aby zrozumieć podstawy MySQL.
Importowanie MySQL
Możemy użyć prostego require instrukcja do zaimportowania biblioteki sqlite przy założeniu, że implementacja Lua została wykonana poprawnie.
mysql = require "luasql.mysql"
Zmienna mysql zapewni dostęp do funkcji poprzez odwołanie się do głównej tabeli mysql.
Konfigurowanie połączenia
Połączenie możemy zestawić, inicjując środowisko MySQL, a następnie tworząc połączenie dla tego środowiska. Jest to pokazane poniżej.
local env = mysql.mysql()
local conn = env:connect('test','root','123456')
Powyższe połączenie połączy się z istniejącym plikiem MySQL i ustanowi połączenie z nowo utworzonym plikiem.
Wykonaj funkcję
Z połączeniem dostępna jest prosta funkcja wykonywania, która pomoże nam wykonać wszystkie operacje bazy danych, od tworzenia, wstawiania, usuwania, aktualizowania i tak dalej. Składnia jest pokazana poniżej -
conn:execute([[ 'MySQLSTATEMENT' ]])
W powyższej składni musimy upewnić się, że conn jest otwarte i istnieje połączenie MySQL i zastąpić „MySQLSTATEMENT” poprawną instrukcją.
Utwórz przykład tabeli
Poniżej pokazano prosty przykład tworzenia tabeli. Tworzy tabelę z dwoma parametrami id typu integer i nazwą typu varchar.
mysql = require "luasql.mysql"
local env = mysql.mysql()
local conn = env:connect('test','root','123456')
print(env,conn)
status,errorString = conn:execute([[CREATE TABLE sample2 (id INTEGER, name TEXT);]])
print(status,errorString )
Po uruchomieniu powyższego programu zostanie utworzona tabela o nazwie sample z dwiema kolumnami, a mianowicie id i name.
MySQL environment (004BB178) MySQL connection (004BE3C8)
0 nil
W przypadku wystąpienia błędu, zamiast zera zostanie zwrócona instrukcja błędu. Poniżej przedstawiono proste stwierdzenie błędu.
LuaSQL: Error executing query. MySQL: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"id INTEGER, name TEXT)' at line 1
Wstaw przykład instrukcji
Poniżej przedstawiono instrukcję wstawiania dla MySQL.
conn:execute([[INSERT INTO sample values('11','Raj')]])
Przykład instrukcji aktualizacji
Poniżej przedstawiono instrukcję aktualizacji MySQL.
conn:execute([[UPDATE sample3 SET name='John' where id ='12']])
Przykład instrukcji usuwania
Poniżej przedstawiono instrukcję usuwania MySQL.
conn:execute([[DELETE from sample3 where id ='12']])
Przykład instrukcji Select
Jeśli chodzi o instrukcję select, musimy przejść przez każdy z wierszy i wyodrębnić wymagane dane. Poniżej przedstawiono prostą instrukcję select.
cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")
while row do
print(string.format("Id: %s, Name: %s", row.id, row.name))
-- reusing the table of results
row = cursor:fetch (row, "a")
end
W powyższym kodzie conn jest otwartym połączeniem MySQL. Za pomocą kursora zwróconego przez instrukcję execute można przejrzeć w pętli odpowiedź tabeli i pobrać wymagane dane wyboru.
Kompletny przykład
Pełny przykład zawierający wszystkie powyższe stwierdzenia podano poniżej.
mysql = require "luasql.mysql"
local env = mysql.mysql()
local conn = env:connect('test','root','123456')
print(env,conn)
status,errorString = conn:execute([[CREATE TABLE sample3 (id INTEGER, name TEXT)]])
print(status,errorString )
status,errorString = conn:execute([[INSERT INTO sample3 values('12','Raj')]])
print(status,errorString )
cursor,errorString = conn:execute([[select * from sample3]])
print(cursor,errorString)
row = cursor:fetch ({}, "a")
while row do
print(string.format("Id: %s, Name: %s", row.id, row.name))
row = cursor:fetch (row, "a")
end
-- close everything
cursor:close()
conn:close()
env:close()
Po uruchomieniu powyższego programu otrzymasz następujące dane wyjściowe.
MySQL environment (0037B178) MySQL connection (0037EBA8)
0 nil
1 nil
MySQL cursor (003778A8) nil
Id: 12, Name: Raj
Wykonywanie transakcji
Transakcje to mechanizm zapewniający spójność danych. Transakcje powinny mieć następujące cztery właściwości -
Atomicity - Albo transakcja zostaje zakończona, albo nic się nie dzieje.
Consistency - Transakcja musi rozpocząć się w stanie zgodnym i pozostawić system w stanie zgodnym.
Isolation - Pośrednie wyniki transakcji nie są widoczne poza bieżącą transakcją.
Durability - Po zatwierdzeniu transakcji efekty są trwałe, nawet po awarii systemu.
Transakcja rozpoczyna się od STARTU TRANSAKCJI; i kończy się instrukcją commit lub rollback.
Rozpocznij transakcję
Aby zainicjować transakcję, musimy wykonać następującą instrukcję w Lua, zakładając, że conn to otwarte połączenie MySQL.
conn:execute([[START TRANSACTION;]])
Transakcja wycofania
Musimy wykonać następującą instrukcję, aby cofnąć zmiany wprowadzone po wykonaniu transakcji startowej.
conn:execute([[ROLLBACK;]])
Zatwierdź transakcję
Musimy wykonać następującą instrukcję, aby zatwierdzić zmiany wprowadzone po wykonaniu transakcji startowej.
conn:execute([[COMMIT;]])
Wiedzieliśmy o MySQL w powyższej sekcji, a następna sekcja wyjaśnia podstawowe operacje SQL. Zapamiętaj transakcje, choć nie zostały one ponownie wyjaśnione dla SQLite3, ale te same instrukcje powinny działać również dla SQLite3.
Importowanie SQLite
Możemy użyć prostej instrukcji wymagania, aby zaimportować bibliotekę SQLite, zakładając, że Twoja implementacja Lua została wykonana poprawnie. Podczas instalacji folder libsql zawierający pliki związane z bazą danych.
sqlite3 = require "luasql.sqlite3"
Zmienna sqlite3 zapewni dostęp do funkcji poprzez odwołanie się do głównej tabeli sqlite3.
Konfigurowanie połączenia
Połączenie możemy zestawić inicjując środowisko SQLite, a następnie tworząc połączenie dla tego środowiska. Jest to pokazane poniżej.
local env = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
Powyższe połączenie połączy się z istniejącym plikiem SQLite lub utworzy nowy plik SQLite i ustanowi połączenie z nowo utworzonym plikiem.
Wykonaj funkcję
Z połączeniem dostępna jest prosta funkcja wykonywania, która pomoże nam wykonać wszystkie operacje bazy danych, od tworzenia, wstawiania, usuwania, aktualizowania i tak dalej. Składnia jest pokazana poniżej -
conn:execute([[ 'SQLite3STATEMENT' ]])
W powyższej składni musimy upewnić się, że conn jest otwarte i istnieje połączenie sqlite3 i zastąpić 'SQLite3STATEMENT' poprawną instrukcją.
Utwórz przykład tabeli
Poniżej pokazano prosty przykład tworzenia tabeli. Tworzy tabelę z dwoma parametrami id typu integer i nazwą typu varchar.
sqlite3 = require "luasql.sqlite3"
local env = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)
status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )
Po uruchomieniu powyższego programu zostanie utworzona tabela o nazwie sample z dwiema kolumnami, a mianowicie id i name.
SQLite3 environment (003EC918) SQLite3 connection (00421F08)
0 nil
W przypadku błędu zamiast nil zostanie zwrócona instrukcja błędu. Poniżej przedstawiono proste stwierdzenie błędu.
LuaSQL: unrecognized token: ""'id' INTEGER, 'name' TEXT)"
Wstaw przykład instrukcji
Poniżej pokazano instrukcję wstawiania dla SQLite.
conn:execute([[INSERT INTO sample values('11','Raj')]])
Przykład instrukcji Select
Jeśli chodzi o instrukcję select, musimy przejść przez każdy z wierszy i wyodrębnić wymagane dane. Poniżej przedstawiono prostą instrukcję select.
cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")
while row do
print(string.format("Id: %s, Name: %s", row.id, row.name))
-- reusing the table of results
row = cursor:fetch (row, "a")
end
W powyższym kodzie conn jest otwartym połączeniem sqlite3. Za pomocą kursora zwróconego przez instrukcję execute można przejrzeć w pętli odpowiedź tabeli i pobrać wymagane dane wyboru.
Kompletny przykład
Pełny przykład zawierający wszystkie powyższe stwierdzenia podano poniżej.
sqlite3 = require "luasql.sqlite3"
local env = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)
status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )
status,errorString = conn:execute([[INSERT INTO sample values('1','Raj')]])
print(status,errorString )
cursor,errorString = conn:execute([[select * from sample]])
print(cursor,errorString)
row = cursor:fetch ({}, "a")
while row do
print(string.format("Id: %s, Name: %s", row.id, row.name))
row = cursor:fetch (row, "a")
end
-- close everything
cursor:close()
conn:close()
env:close()
Po uruchomieniu powyższego programu otrzymasz następujące dane wyjściowe.
SQLite3 environment (005EC918) SQLite3 connection (005E77B0)
0 nil
1 nil
SQLite3 cursor (005E9200) nil
Id: 1, Name: Raj
Z pomocą tej biblioteki libsql możemy wykonać wszystkie dostępne zapytania. Dlatego nie poprzestawaj na tych przykładach. Eksperymentuj z różnymi instrukcjami zapytania dostępnymi w odpowiednich MySQL, SQLite3 i innych obsługiwanych bazach danych w Lua.
Lua jest używana w wielu silnikach gier ze względu na prostą strukturę językową i składnię. Funkcja zbierania śmieci jest często bardzo przydatna w grach, które zużywają dużo pamięci ze względu na bogatą grafikę, która jest używana. Niektóre silniki gier korzystające z Lua obejmują -
- Corona SDK
- Gideros Mobile
- ShiVa3D
- Moai SDK
- LOVE
- CryEngine
Każdy z tych silników gier jest oparty na Lua i każdy z nich posiada bogaty zestaw API. Przyjrzymy się w skrócie możliwościom każdego z nich.
Corona SDK
Corona SDK to wieloplatformowy silnik gier mobilnych, który obsługuje platformy iPhone, iPad i Android. Dostępna jest bezpłatna wersja Corona SDK, której można używać do małych gier z ograniczonymi funkcjami. W razie potrzeby możesz uaktualnić do innych wersji.
Corona SDK zapewnia szereg funkcji, w tym:
- Interfejsy API do obsługi fizyki i kolizji
- Internetowe i sieciowe interfejsy API
- Game Network API
- Ads API
- API Analytics
- Interfejsy API baz danych i systemu plików
- Crypto i Math APIs
- Audio i Media API
Tworzenie aplikacji przy użyciu powyższych interfejsów API jest łatwiejsze i szybsze niż używanie natywnych interfejsów API oddzielnie dla systemów iOS i Android.
Gideros Mobile
Gideros zapewnia wieloplatformowy pakiet SDK do tworzenia gier na iOS i Androida. Można go używać za darmo z splashem wykonanym z Gideros. Niektóre z uderzających zalet Gideoros obejmują:
Development IDE - Zapewnia własne IDE, które ułatwia tworzenie aplikacji Gideros.
Instant testing- Podczas tworzenia gry można ją przetestować na prawdziwym urządzeniu przez Wi-Fi w zaledwie 1 sekundę. Nie musisz tracić czasu na eksport lub proces wdrażania.
Plugins- Możesz łatwo rozszerzyć rdzeń za pomocą wtyczek. Zaimportuj istniejący kod (C, C ++, Java lub Obj-C), powiąż z Lua i zinterpretuj go bezpośrednio. Dziesiątki wtyczek open source są już opracowane i gotowe do użycia.
Clean OOP approach - Gideros zapewnia własny system klas ze wszystkimi podstawowymi standardami OOP, umożliwiając pisanie czystego i wielokrotnego użytku kodu dla dowolnej z przyszłych gier.
Native speed - Opracowana w oparciu o C / C ++ i OpenGL, Twoja gra działa z natywną prędkością iw pełni wykorzystuje moc procesorów i kart graficznych znajdujących się pod spodem.
ShiVa3D
ShiVa3D to jeden z silników gier 3D, który zapewnia edytor graficzny przeznaczony do tworzenia aplikacji i gier wideo na WWW, konsole i urządzenia mobilne. Obsługuje wiele platform, w tym Windows, Mac, Linux, iOS, Android, BlackBerry, Palm OS, Wii i WebOS.
Niektóre z głównych funkcji obejmują
- Standardowe wtyczki
- API modyfikacji siatki
- IDE
- Wbudowany edytor terenu, oceanu i animacji
- Obsługa silnika fizyki ODE
- Pełna kontrola nad lightmapą
- Podgląd na żywo materiałów, cząstek, śladów i HUDów
- Obsługa formatu wymiany Collada
Wersja internetowa Shiva3d jest całkowicie bezpłatna i inne wersje, które subskrybujesz.
Moai SDK
Moai SDK to wieloplatformowy silnik gier mobilnych, który obsługuje platformy iPhone, iPad i Android. Platforma Moai początkowo składała się z Moai SDK, silnika gier typu open source oraz Moai Cloud, platformy chmurowej jako usługi do hostowania i wdrażania usług gier. Teraz chmura Moai jest wyłączona i dostępny jest tylko silnik gry.
Moai SDK działa na wielu platformach, w tym iOS, Android, Chrome, Windows, Mac i Linux.
MIŁOŚĆ
LOVE to framework, którego możesz używać do tworzenia gier 2D. Jest darmowy i open-source. Obsługuje platformy Windows, Mac OS X i Linux.
Zapewnia wiele funkcji, które obejmują,
- Audio API
- Interfejs API systemu plików
- Interfejsy API klawiatury i joysticka
- Math API
- Interfejsy API okien i myszy
- Physics API
- API systemowe i czasowe
CryEngine
CryEngine to silnik gier opracowany przez niemieckiego twórcę gier Crytek. Ewoluował z generacji 1 do generacji 4 i jest zaawansowanym rozwiązaniem programistycznym. Obsługuje gry na PC, Xbox 360, PlayStation3 i WiiU.
Zapewnia wiele funkcji, które obejmują,
Efekty wizualne, takie jak naturalne oświetlenie i dynamiczne miękkie cienie, dynamiczne globalne oświetlenie w czasie rzeczywistym, objętość propagacji światła, cieniowanie cząstek, teselacja i tak dalej.
System animacji postaci i system indywidualizacji postaci.
Parametryczna animacja szkieletu i unikalny dedykowany edytor animacji twarzy
Systemy AI, takie jak wielowarstwowa siatka nawigacyjna i system punktów taktycznych. Zapewnia również przyjazny dla projektantów system edycji AI.
W miksowaniu i profilowaniu gier, dynamicznych dźwiękach systemu dźwiękowego i interaktywnej muzyce i tak dalej.
Funkcje fizyczne, takie jak deformacja proceduralna i zaawansowana fizyka linowa.
Uwaga końcowa
Każdy z tych zestawów SDK gier / frameworków ma swoje zalety i wady. Właściwy wybór między nimi ułatwia zadanie i pozwala spędzić z nim lepiej czas. Tak więc, zanim go użyjesz, musisz znać wymagania swojej gry, a następnie przeanalizować, która spełnia wszystkie Twoje potrzeby, a następnie z nich korzystać.
Standardowe biblioteki Lua zapewniają bogaty zestaw funkcji, które są implementowane bezpośrednio przez C API i są wbudowane w język programowania Lua. Biblioteki te zapewniają usługi w języku programowania Lua, a także usługi zewnętrzne, takie jak operacje na plikach i bazach danych.
Te standardowe biblioteki wbudowane w oficjalne C API są dostarczane jako oddzielne moduły C. Obejmuje następujące -
- Biblioteka podstawowa, która zawiera bibliotekę podrzędną programu
- Biblioteka modułów
- Manipulacja strunami
- Manipulacja stołem
- Biblioteka matematyczna
- Plik wejściowy i wyjściowy
- Funkcje systemu operacyjnego
- Funkcje debugowania
Biblioteka podstawowa
Korzystaliśmy z podstawowej biblioteki w całym samouczku w ramach różnych tematów. Poniższa tabela zawiera linki do powiązanych stron i listę funkcji, które są omówione w różnych częściach tego samouczka Lua.
Sr.No. | Biblioteka / metoda i cel |
---|---|
1 | Error Handling Obejmuje funkcje obsługi błędów, takie jak assert, error, jak wyjaśniono w Lua - Obsługa błędów . |
2 | Memory Management Zawiera funkcje automatycznego zarządzania pamięcią związane z usuwaniem elementów bezużytecznych, jak wyjaśniono w Lua - Garbage Collection . |
3 | dofile ([filename]) Otwiera plik i wykonuje zawartość pliku jako fragment. Jeśli nie zostanie przekazany żaden parametr, funkcja ta wykonuje zawartość standardowego wejścia. Błędy zostaną przekazane wywołującemu. |
4 | _G Tak więc jest to zmienna globalna, która przechowuje środowisko globalne (to znaczy _G._G = _G). Sam Lua nie używa tej zmiennej. |
5 | getfenv ([f]) Zwraca bieżące środowisko używane przez funkcję. f może być funkcją Lua lub liczbą określającą funkcję na tym poziomie stosu - Poziom 1 to funkcja wywołująca getfenv. Jeśli podana funkcja nie jest funkcją Lua lub f wynosi 0, getfenv zwraca środowisko globalne. Wartość domyślna f to 1. |
6 | getmetatable (object) Jeśli obiekt nie ma metatabeli, zwraca nil. W przeciwnym razie, jeśli metatablica obiektu ma pole „__metatable”, zwraca skojarzoną wartość. W przeciwnym razie zwraca metatabelę danego obiektu. |
7 | ipairs (t) Ta funkcja pobiera indeksy i wartości z tabel. |
8 | load (func [, chunkname]) Ładuje fragment za pomocą funkcji func, aby pobrać jego fragmenty. Każde wywołanie funkcji func musi zwrócić ciąg, który jest zgodny z poprzednimi wynikami. |
9 | loadfile ([filename])) Podobne do load, ale pobiera porcję z pliku nazwa_pliku lub ze standardowego wejścia, jeśli nie podano nazwy pliku. |
10 | loadstring (string [, chunkname]) Podobne do load, ale pobiera fragment z podanego ciągu. |
11 | next (table [, index]) Umożliwia programowi przechodzenie przez wszystkie pola tabeli. Jego pierwszym argumentem jest tabela, a drugim indeksem w tej tabeli. next zwraca następny indeks tabeli i związaną z nim wartość. |
12 | pairs (t) Zawiesza uruchomiony program. Parametr przekazany do tej metody działa jako dodatkowe wartości zwracane do funkcji wznawiania. |
13 | print (...) Zawiesza uruchomiony program. Parametr przekazany do tej metody działa jako dodatkowe wartości zwracane do funkcji wznawiania. |
14 | rawequal (v1, v2) Sprawdza, czy v1 jest równe v2, bez wywoływania żadnej metametody. Zwraca wartość logiczną. |
15 | rawget (table, index) Pobiera rzeczywistą wartość tabeli [indeks], bez wywoływania żadnej metametody. tabela musi być stołem; indeks może mieć dowolną wartość. |
16 | rawset (table, index, value) Ustawia rzeczywistą wartość tabeli [indeks] na wartość, bez wywoływania żadnej metametody. tabela musi być tabelą, indeksować dowolną wartość inną niż nil i zawierać dowolną wartość Lua. Ta funkcja zwraca tabelę. |
17 | select (index, ...) Jeśli indeks jest liczbą, zwraca wszystkie argumenty po indeksie numeru argumentu. W przeciwnym razie indeks musi być ciągiem „#”, a funkcja select zwraca całkowitą liczbę otrzymanych dodatkowych argumentów. |
18 | setfenv (f, table) Ustawia środowisko, które ma być używane przez daną funkcję. f może być funkcją Lua lub liczbą określającą funkcję na tym poziomie stosu - Poziom 1 to funkcja wywołująca setfenv. setfenv zwraca podaną funkcję. W szczególnym przypadku, gdy f wynosi 0, setfenv zmienia środowisko działającego wątku. W tym przypadku setfenv nie zwraca żadnych wartości. |
19 | setmetatable (table, metatable) Ustawia metatabelę dla danej tabeli. (Nie możesz zmienić metatabli innych typów z Lua, tylko z C.) Jeśli metatablica jest zerowa, usuwa metatabelę z podanej tabeli. Jeśli oryginalna metatablica ma pole „__metatable”, zgłasza błąd. Ta funkcja zwraca tabelę. |
20 | tonumber (e [, base]) Próbuje zamienić argument na liczbę. Jeśli argument jest już liczbą lub łańcuchem zamiennym na liczbę, to tonumber zwraca tę liczbę; w przeciwnym razie zwraca nil. |
21 | tostring (e) Odbiera argument dowolnego typu i konwertuje go na ciąg w rozsądnym formacie. Aby uzyskać pełną kontrolę nad konwersją liczb, użyj string.format. |
22 | type (v) Zwraca typ jedynego argumentu zakodowanego jako ciąg. Możliwe wyniki tej funkcji to „nil” (ciąg znaków, a nie wartość nil), „liczba”, „ciąg znaków”, „wartość logiczna”, „tabela”, „funkcja”, „wątek” i „dane użytkownika”. |
23 | unpack (list [, i [, j]]) Zwraca elementy z podanej tabeli. |
24 | _VERSION Zmienna globalna (nie funkcja), która przechowuje łańcuch zawierający aktualną wersję interpretera. Bieżąca zawartość tej zmiennej to „Lua 5.1”. |
25 | Coroutines Zawiera funkcje manipulacji programami, jak wyjaśniono w Lua - Coroutines . |
Biblioteka modułów
Biblioteka modułów zapewnia podstawowe funkcje do ładowania modułów w Lua. Eksportuje jedną funkcję bezpośrednio w środowisku globalnym: require. Wszystko inne jest eksportowane w pakiecie tabel. Szczegóły dotyczące biblioteki modułów zostały wyjaśnione we wcześniejszym rozdziale Lua - samouczek dotyczący modułów .
Manipulacja strunami
Lua zapewnia bogaty zestaw funkcji do manipulacji na napisach. Wcześniejszy samouczek Lua - Strings omawia to szczegółowo.
Manipulacja stołem
Lua polega na tabelach w prawie każdym fragmencie swoich operacji. Wcześniejszy samouczek Lua - Tables omawia to szczegółowo.
Plik wejściowy i wyjściowy
Często potrzebujemy możliwości przechowywania danych w programowaniu, a zapewniają to standardowe funkcje biblioteczne dla plików I / O w Lua. Zostało to omówione we wcześniejszym samouczku Lua - File I / O.
Funkcje debugowania
Lua zapewnia bibliotekę debugowania, która zapewnia wszystkie prymitywne funkcje potrzebne do stworzenia własnego debugera. Zostało to omówione we wcześniejszym samouczku Lua - Debugowanie .
Często potrzebujemy operacji matematycznych w obliczeniach naukowych i inżynieryjnych i możemy to wykorzystać, korzystając ze standardowej matematyki biblioteki Lua. Lista funkcji dostępnych w bibliotece matematycznej jest pokazana w poniższej tabeli.
Sr.No. | Biblioteka / metoda i cel |
---|---|
1 | math.abs (x) Zwraca wartość bezwzględną x. |
2 | math.acos (x) Zwraca arcus cosinus z x (w radianach). |
3 | math.asin (x) Zwraca arcus sinus z x (w radianach). |
4 | math.atan (x) Zwraca styczną łuku dla x (w radianach). |
5 | math.atan2 (y, x) Zwraca styczną łuku dla y / x (w radianach), ale używa znaków obu parametrów, aby znaleźć ćwiartkę wyniku. (Również poprawnie obsługuje przypadek, w którym x jest równe zero). |
6 | math.ceil (x) Zwraca najmniejszą liczbę całkowitą większą lub równą x. |
7 | math.cos (x) Zwraca cosinus funkcji x (przyjmuje się, że jest on wyrażony w radianach). |
8 | math.cosh (x) Zwraca cosinus hiperboliczny z x. |
9 | math.deg (x) Zwraca kąt x (podany w radianach) w stopniach. |
10 | math.exp (x) Zwraca wartość e power x. |
11 | math.floor (x) Zwraca największą liczbę całkowitą mniejszą lub równą x. |
12 | math.fmod (x, y) Zwraca pozostałą część z dzielenia x przez y, która zaokrągla iloraz w kierunku zera. |
13 | math.frexp (x) Zwraca mi e takie, że x = m2e, e jest liczbą całkowitą, a wartość bezwzględna m należy do zakresu [0,5, 1) (lub zero, gdy x wynosi zero). |
14 | math.huge Wartość HUGE_VAL, wartość większa lub równa dowolnej innej wartości liczbowej. |
15 | math.ldexp (m, e) Zwraca m2e (e powinno być liczbą całkowitą). |
16 | math.log (x) Zwraca logarytm naturalny z x. |
17 | math.log10 (x) Zwraca logarytm dziesiętny z x. |
18 | math.max (x, ...) Zwraca maksymalną wartość spośród jej argumentów. |
19 | math.min (x, ...) Zwraca minimalną wartość spośród swoich argumentów. |
20 | math.modf (x) Zwraca dwie liczby, część całkowitą x i część ułamkową x. |
21 | math.pi Wartość pi. |
22 | math.pow (x, y) Zwraca xy. (Aby obliczyć tę wartość, możesz również użyć wyrażenia x ^ y). |
23 | math.rad (x) Zwraca kąt x (podany w stopniach) w radianach. |
24 | math.random ([m [, n]]) Ta funkcja jest interfejsem do prostej funkcji generatora pseudolosowego rand dostarczonej przez ANSI C. Wywołana bez argumentów zwraca jednolitą pseudolosową liczbę rzeczywistą z zakresu [0,1). Funkcja math.random wywołana z liczbą całkowitą m zwraca jednolitą pseudolosową liczbę całkowitą z zakresu [1, m]. Funkcja math.random wywołana z dwiema liczbami całkowitymi m i n zwraca jednolitą pseudolosową liczbę całkowitą z zakresu [m, n]. |
25 | math.randomseed (x) Ustawia x jako „ziarno” dla generatora pseudolosowego: równe nasiona tworzą równe sekwencje liczb. |
26 | math.sin (x) Zwraca sinus z x (przyjmuje się, że jest on wyrażony w radianach). |
27 | math.sinh (x) Zwraca sinus hiperboliczny z x. |
28 | math.sqrt (x) Zwraca pierwiastek kwadratowy z x. (Aby obliczyć tę wartość, możesz również użyć wyrażenia x ^ 0,5). |
29 | math.tan (x) Zwraca tangens x (przyjmuje się, że jest on wyrażony w radianach). |
30 | math.tanh (x) Zwraca hiperboliczną styczną z x. |
Funkcje trygonometryczne
Poniżej przedstawiono prosty przykład użycia funkcji trygonometrycznej.
radianVal = math.rad(math.pi / 2)
io.write(radianVal,"\n")
-- Sin value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.sin(radianVal)),"\n")
-- Cos value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.cos(radianVal)),"\n")
-- Tan value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.tan(radianVal)),"\n")
-- Cosh value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.cosh(radianVal)),"\n")
-- Pi Value in degrees
io.write(math.deg(math.pi),"\n")
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
0.027415567780804
0.0
1.0
0.0
1.0
180
Inne popularne funkcje matematyczne
Poniżej przedstawiono prosty przykład użycia typowych funkcji matematycznych.
-- Floor
io.write("Floor of 10.5055 is ", math.floor(10.5055),"\n")
-- Ceil
io.write("Ceil of 10.5055 is ", math.ceil(10.5055),"\n")
-- Square root
io.write("Square root of 16 is ",math.sqrt(16),"\n")
-- Power
io.write("10 power 2 is ",math.pow(10,2),"\n")
io.write("100 power 0.5 is ",math.pow(100,0.5),"\n")
-- Absolute
io.write("Absolute value of -10 is ",math.abs(-10),"\n")
--Random
math.randomseed(os.time())
io.write("Random number between 1 and 100 is ",math.random(),"\n")
--Random between 1 to 100
io.write("Random number between 1 and 100 is ",math.random(1,100),"\n")
--Max
io.write("Maximum in the input array is ",math.max(1,100,101,99,999),"\n")
--Min
io.write("Minimum in the input array is ",math.min(1,100,101,99,999),"\n")
Kiedy uruchomimy powyższy program, otrzymamy następujące dane wyjściowe.
Floor of 10.5055 is 10
Ceil of 10.5055 is 11
Square root of 16 is 4
10 power 2 is 100
100 power 0.5 is 10
Absolute value of -10 is 10
Random number between 1 and 100 is 0.22876674703207
Random number between 1 and 100 is 7
Maximum in the input array is 999
Minimum in the input array is 1
Powyższe przykłady to tylko kilka typowych przykładów, możemy użyć biblioteki matematycznej w zależności od naszych potrzeb, więc spróbuj użyć wszystkich funkcji, aby być bardziej znanym.
W każdej aplikacji często wymagany jest dostęp do funkcji na poziomie systemu operacyjnego i jest udostępniany wraz z biblioteką systemu operacyjnego. Lista dostępnych funkcji znajduje się w poniższej tabeli.
Sr.No. | Biblioteka / metoda i cel |
---|---|
1 | os.clock () Zwraca przybliżoną ilość w sekundach czasu procesora używanego przez program. |
2 | os.date ([format [, time]]) Zwraca ciąg lub tabelę zawierającą datę i godzinę sformatowaną zgodnie z podanym formatem ciągu. |
3 | os.difftime (t2, t1) Zwraca liczbę sekund od czasu t1 do czasu t2. W POSIX, Windows i niektórych innych systemach ta wartość to dokładnie t2-t1. |
4 | os.execute ([command]) Ta funkcja jest odpowiednikiem systemu funkcji ANSI C. Przekazuje polecenie do wykonania przez powłokę systemu operacyjnego. Jego pierwszy wynik jest prawdziwy, jeśli polecenie zakończyło się pomyślnie, lub zero w przeciwnym razie. |
5 | os.exit ([code [, close]) Wywołuje funkcję ANSI C exit, aby zakończyć program hosta. Jeśli kod jest prawdziwy, zwracany stan to EXIT_SUCCESS; jeśli kod jest fałszywy, zwracany stan to EXIT_FAILURE; jeśli kod jest liczbą, zwracanym stanem jest ta liczba. |
6 | os.getenv (varname) Zwraca wartość zmiennej środowiskowej procesu nazwa_zmiennej lub nil, jeśli zmienna nie jest zdefiniowana. |
7 | os.remove (filename) Usuwa plik (lub pusty katalog w systemach POSIX) o podanej nazwie. Jeśli ta funkcja nie powiedzie się, zwraca nil oraz ciąg opisujący błąd i kod błędu. |
8 | os.rename (oldname, newname) Zmienia nazwę pliku lub katalogu o nazwie stara nazwa na nowa nazwa. Jeśli ta funkcja nie powiedzie się, zwraca nil oraz ciąg opisujący błąd i kod błędu. |
9 | os.setlocale (locale [, category]) Ustawia bieżące ustawienia regionalne programu. locale to zależny od systemu łańcuch, określający locale; kategoria to opcjonalny ciąg opisujący kategorię do zmiany: „wszystkie”, „sortowanie”, „typ”, „pieniężne”, „numeryczne” lub „czas”; kategorią domyślną jest „wszystkie”. Funkcja zwraca nazwę nowego ustawienia narodowego lub nil, jeśli żądanie nie może zostać uwzględnione. |
10 | os.time ([table]) Zwraca bieżący czas wywołania bez argumentów lub czas reprezentujący datę i godzinę określoną przez daną tabelę. Ta tabela musi zawierać pola rok, miesiąc i dzień oraz może zawierać pola godzina (wartość domyślna to 12), min (wartość domyślna to 0), sekundy (wartość domyślna to 0) i isdst (wartość domyślna to zero). Opis tych pól można znaleźć w funkcji os.date. |
11 | os.tmpname () Zwraca ciąg z nazwą pliku, której można użyć jako pliku tymczasowego. Plik musi zostać jawnie otwarty przed użyciem i jawnie usunięty, gdy nie jest już potrzebny. |
Typowe funkcje systemu operacyjnego
Poniżej przedstawiono prosty przykład użycia typowych funkcji matematycznych.
-- Date with format
io.write("The date is ", os.date("%m/%d/%Y"),"\n")
-- Date and time
io.write("The date and time is ", os.date(),"\n")
-- Time
io.write("The OS time is ", os.time(),"\n")
-- Wait for some time
for i=1,1000000 do
end
-- Time since Lua started
io.write("Lua started before ", os.clock(),"\n")
Gdy uruchomimy powyższy program, uzyskamy wyniki podobne do poniższych.
The date is 01/25/2014
The date and time is 01/25/14 07:38:40
The OS time is 1390615720
Lua started before 0.013
Powyższe przykłady to tylko kilka typowych przykładów, możemy użyć biblioteki systemu operacyjnego w zależności od naszych potrzeb, więc spróbuj użyć wszystkich funkcji, aby być bardziej znanym. Istnieją funkcje takie jak usuń, które pomagają w usuwaniu pliku, wykonaj, które pomagają nam wykonywać polecenia systemu operacyjnego, jak wyjaśniono powyżej.