Kapcsolatok

Lua bemutatása. Mindent tudni akar. Lua nyelv A lua tanulása a semmiből

Nemrég egy közeli barátom elment interjúra egy helyi játékfejlesztő cégnél. Nem fogok itt neveket megnevezni, kivéve azt, hogy ez egy nagy játékfejlesztő butik volt Vancouverben. Nem kapott munkát, de ma már nem róla van szó. Személy szerint úgy gondolom, hogy ennek egyik oka az volt, hogy nem volt barátságos az általuk használt szkriptnyelvvel.

Bevezetés

Ezen a területen vagyok, mivel játékprogramozást tanítok a diákoknak, de ez egy olyan téma, amelyre korábban nem fordítottam kellő figyelmet. Az Unreal Scriptet a "Létező használata" tanfolyam részeként ismertetjük. De valójában nem tekintettük a szkriptmotort a segédprogramok részének vagy a motor részének. Így hát egy weboldallal felvértezve úgy döntöttem, hogy áttöröm ezt a kis akadályt. Az eredményt ebben a dokumentumban ismertetjük.

Az egyetlen dolog, hogy nem tudom, mekkora lesz ez a dokumentum. Több apró részre bonthatom, vagy teljes egészében kiadhatom egy hosszú tirádában az elejétől a végéig. Na mindegy, ezt kicsit később fogom eldönteni, amikor értelmesebb és következetesebb formátumba formázom a bejegyzéseimet.

Miért és miért nem?

Először is, miért használjunk szkriptnyelvet? A legtöbb játéklogika megírható szkriptnyelven különféle célokra, ahelyett, hogy egy játékmotor részeként programoznák. Például betöltés vagy szint inicializálás. A pálya betöltése után érdemes lefordítani a jelenetet a játéktervbe, vagy mutatni egy előzetes szöveget. Egy parancsfájlrendszer használatával bizonyos játékobjektumokat végrehajthat bizonyos feladatokat. Ezenkívül fontolja meg a mesterséges intelligencia alkalmazását. A nem játékos karaktereknek tudniuk kell, mit kell tenniük. Minden egyes NPC "kézzel" programozása a játékmotor testében szükségtelenül megnehezítené a feladatot. Ha meg akarja változtatni egy NPC viselkedését, újra kell fordítania a projektet. Egy szkriptrendszerrel ezt interaktívan, a viselkedés megváltoztatásával és a beállítások mentésével teheti meg.

Kicsit érintettem ezt a problémát az utolsó bekezdésben, kicsit később lesz még szó róla. A kérdés az, hogy miért ne írhatnánk le a logikát kizárólag C/C++ nyelven? Leegyszerűsítve a jövőben a programozónak megvan az a ténye, hogy minden közvetlenül rá esik, és ennek megfelelően indul el a játék kódjával, ugyanakkor meg kell írnia a motort és a segédprogramokat is, stb. De most már egy egyszerű szkriptnyelvvel átrakhatunk néhány funkcionalitási feladatot a szinttervezőkre. Elkezdhetnek kavarni a szinttel, és optimalizálhatják a játékmenetet. Íme a tényleges példa:

Képzeljük el, hogy Joe, a szerencsétlen programozónk maga írja az egész játékmotort, az eszközöket és a játéklogikát. Igen, Joe-nak nehéz dolga lesz, de tegyük fel, hogy nem érdekli. Nálunk van Brandon, a játéktervező is. Brandon elég okos gyerek, remek ötletekkel a játékhoz. Így a kódolónk, Joe feltérképezi és megvalósítja az összes játéklogikát a Brandon kezdeti tervezete alapján általa kifejlesztett eszközkészlettel. Az irodában minden rendben van. Az első szakasz véget ért, Joe és Brandon a tanácsteremben ülnek, és ellenőrzik jelentős munkájukat. Brandon észrevesz néhány problémát a játékmenet nem megfelelően működik. Így Joe visszatér a kódhoz, és elvégzi a szükséges változtatásokat. Ez a folyamat egy napig is eltarthat, legalábbis ha nem triviális változásról van szó. Aztán még egy nap a projekt újrafordítására. Annak érdekében, hogy ne veszítsen egy plusz napot, a legtöbb iroda egyik napról a másikra elhagyja az összeszerelési folyamatot. Tehát, amint látjuk, 24 óra telik el, mire Brandon meglátja a szükséges változtatást.

Most képzeljük el, hogy főszereplőnk, Joe úgy dönt, hogy a játék logikájának megvalósítása a forgatókönyv-motort használja a javára. Eleinte eltart egy ideig, de úgy érzi, hosszú távon előnyös lesz. Így néhány funkciót áthelyez a játékmotorról a játék szkriptrendszerére. A korábban említett szkriptrendszerbe minden játéklogikát is beír. És így, amikor találkozik Brandonnal, és a tervező észrevesz valamit, ami nem egyezik az elképzelésével, Joe gyorsan kinyitja a konzolt, módosít néhányat a forgatókönyvön, újraindítja a játékot, és már látja is az új viselkedést. A változtatások azonnal végrehajthatók és azonnal megjeleníthetők, ahelyett, hogy az újrafordításra várnánk. És ha Joe kifejezetten kifejező volt, akkor a szkriptrendszer használható a segédprogramokhoz, és elérhető lenne a szinttervezők számára szintek építésekor. Ha ezen az úton haladunk, akkor egy kis edzéssel a pályatervezők maguk állíthatják be a játék eseményeit, például triggereket, ajtókat, egyéb játékeseményeket, és élvezhetik az életet anélkül, hogy megerőltetnék a programozót.

Ez egy meglehetősen mesterkélt példa, és lehet, hogy kissé túlzás, de remélem, megmutatja a megközelítések közötti különbséget. Tehát ezzel a modellel megpróbálunk elmozdulni az automatikusan kezelt adatok felé. Tehát lényegében merre tartunk:

  1. A kódolót a motor/eszköz kód írása érdekli, nem a játék logikája.
  2. Az idő a játék motorjának/eszközeinek megírásával telt.
  3. A tervezők szeretnek "játszani" a dolgokkal. A szkriptelés szabadságot ad számukra a tervezési szintek és funkcionalitás meghatározásához. Nagyobb rugalmasságot biztosít számukra, hogy olyan dolgokkal kísérletezzenek, amelyekhez általában programozót vennének igénybe.
  4. Ne fordítsa újra, ha meg akarja változtatni a játék funkcionalitását. Csak változtassa meg a forgatókönyvet.
  5. Meg akarja szakítani a kapcsolatot a gépi kód és a játékkód között. Két különálló résznek kell lennie. Így kényelmes lesz a motort használni a következő folytatásokhoz (remélem).

Itt teszek néhány jóslatot. 5 éven belül a szinttervezőknek többet kell tenniük, mint pusztán pályákat készíteni. Tudniuk kell használni a forgatókönyvet játékjelenetekhez. Több előrelátó vállalat is alkalmazta már ezt a megközelítést. Ezt a fajta integrációt láthatja az olyan szerkesztőkben is, mint az UnrealEd és az Aurora Toolset Bioware.

Magyarázat és retorika

Remélem, most már bevállaltad a szavaimat, és be akartál építeni egy script-komponenst a játékodba. És a következő kérdés: hogyan a fenébe csinálod?

A szkriptkomponensemhez egy befecskendezhető szkriptmotort fogok használni Lua. Az elején leszögezem, hogy nem vagyok szakértő a lua nyelvben, de ez egy viszonylag egyszerű nyelv, és nem igényel fárasztó tanulást az elsajátítása. A következő példák némelyike, amelyeken végigfutok, meglehetősen egyszerű. A dokumentum végén további háttéranyagot is mellékelek. Őszintén szólva, vannak más szkriptnyelvek is, mint például a Small, Simkin, Python, Perl. A Lua azonban szép és tiszta nyelv. Ez igazán jó előny.

A Lua nyílt forráskódú. Ez azért jó, mert: (a) megkapod a nyelv forrását, és bármit turkálhatsz benne, (b) ingyenes. Pénzkidobás nélkül használhatja kereskedelmi alkalmazásokban. Nos, a nem kereskedelmi projektekhez érted ingyen == jó.

Tehát ki használja jelenleg a Luát? A Lua-t egy sharashka íróasztal írja, és csak a szegények használják? Hmmm... nem igazán. Lua tegnap nem jelent meg, és meglehetősen híres személyiségek használták:

  • Lucasarts
    • Grim Fandango
    • Menekülés a Majomszigetről
  • bioware
    • Soha téli éjszakák

Oké, elég a lua fejlesztők ki-kicsodájából. A lua weboldalán meg is nézheti.

Kezdjük nagyon egyszerűen. Az első dolog, amit meg kell építenünk, megmutatja, hogyan használjuk a lua interpretert. Mi szükséges ehhez:

  1. Lua tolmács kód beszerzése.
  2. A fejlesztői környezet beállítása.
  3. Tolmács építése a semmiből.

Hé, azt hittem, hogy eleget rikácsoltál?

Nos, ez elég? Szóval, térjünk az üzlethez. Az összes Lua forráskódot letöltheti a hivatalos webhelyről. Szintén szeretném felhívni a figyelmet arra, hogy a lua 5.0 új verziója van a láthatáron. Ebben a cikkben nem fogom ezt a verziót tárgyalni. Később foglalkozom vele, de egyelőre a 4.0.1-et használjuk.

Az első dolog, amit meg fogunk tenni, az a lua könyvtár felépítése. Így nem kell minden alkalommal feltüntetnünk a forrásokat a projekt felépítésekor. Nem nehéz, és nem is ez a célja az óráinknak. Ezért e cikk részeként előre felvettem a könyvtárat. Ehhez a példához statikus könyvtárat használtam. Igen, lehet, hogy DLL-ként építeném, de egy script rendszerhez a statikus könyvtár valamivel gyorsabb. Megjegyzés: nem sokkal, de gyorsabban.

Mai vendégünk a rejtett front igazi harcosa. Láthattad már játékokban (World of Warcraft, Angry Birds, X-Plane, S.T.A.L.K.E.R.) vagy Adobe termékekben (Lightroom), de nem is gondoltál a létezésére. Közben ez a nyelv majdnem 25 éves, és ez idő alatt csendben egy kicsit jobbá tette a virtuális életünket.

Rövid információ

A Lua 1993-ban született volna a Rio de Janeiro-i Katolikus Egyetemen. A nevet portugálból Holdnak fordítják, és az alkotók arra kérnek, hogy ne LUA-t írjanak, ne adj isten, valaki rövidítésnek vegye a nevet. Ez egy többparadigmás szkriptnyelv, amely a prototipikus OOP-modellt használja.

A gépelés itt dinamikus, a metatáblák pedig az öröklődés megvalósítására szolgálnak, vagyis ez egy nagyszerű eszköz a termék képességeinek bővítésére. Kompaktsága miatt pedig szinte bármilyen platformon használható. Ítélje meg maga: a Lua 5.3.4 tarball mindössze 296 kilobájtot nyom (tömörítetlen - 1,1 megabájt), a Linuxhoz készült interpreter (C-ben írva) 182-246 kilobájt, a szabványos könyvtárkészlet pedig további 421 kilobájt.

A kód

Megjelenésében és szolgáltatásaiban a Lua egy újabb kísérletnek tűnik a JavaScript átdolgozására, ha nem az a tény, hogy az utóbbi két évvel később jelent meg. Nézd meg magad:

Kezdjük a hagyományossal:

print ("Hello world")

Egyetértek, ismerős és nem túl informatív. A Lua-ismeret szempontjából érdekesebb példa egy bemeneti szám faktoriálisának kiszámítása:

Funkció tény(n)
ha n == 0, akkor
vissza 1
más
return n * tény(n-1)
vége
vége

Print("adjon meg egy számot:")
a = io.read("*szám") -- szám beolvasása
nyomtatás (tény(a))

Minden nagyon világos. A Lua egyébként támogatja a párhuzamos hozzárendelést:

Végezetül egy meglehetősen egyszerű példa a könyvtárak használatára:

#beleértve
#beleértve
#beleértve
#beleértve
#beleértve

int main(void)(
char buff;
int hiba;
lua_State *L = lua_open(); /* megnyitja a Lua-t */
luaopen_base(L); /* megnyitja az alapkönyvtárat */
luaopen_table(L); /* megnyitja a táblakönyvtárat */
luaopen_io(L); /* megnyitja az I/O könyvtárat */
luaopen_string(L); /* megnyitja a lib karakterláncot. */
luaopen_math(L); /* megnyitja a matematikai lib. */

While (fgets(buff, sizeof(buff), stdin) != NULL) (
hiba = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
lua_pcall(L, 0, 0, 0);
ha (hiba) (
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1); /* pop hibaüzenet a veremből */
}
}

Lua_close(L);
visszatérés 0;
}

Előnyök és hátrányok

Szóval mi a jó Luában?

Először is, amint már említettük, a kompaktsága és azzal a ténnyel párosulva, hogy a forráskód C nyelven íródott, teljes interakciót kap a bolygó egyik legnépszerűbb nyelvével és az elérhető platformok széles skálájával.

Fejlesztési környezetek

LDT (Lua Development Tools) az Eclipse-hez – az egyik legnépszerűbb IDE kiterjesztése;

A ZeroBrane Studio egy speciális, Lua nyelven írt környezet;

A Decoda nem a legnépszerűbb cross-platform IDE, de egy alternatíva;

A SciTE egy jó szerkesztő, amely teljes mértékben támogatja a Lua-t;

WoWUIDesigner – találd ki, melyik játékhoz segít ez a környezet a szkriptek feldolgozásához, beleértve a Lua-belieket is?

Hasznos Linkek

http://www.lua.org/home.html - hivatalos oldal minden szükséges információval, oktatóanyaggal, könyvekkel, dokumentációval és még némi humorral is;

http://tylerneylon.com/a/learn-lua/ – nagyszerű oktatóanyag Tyler Neylontól. Alkalmas gyakorlattal rendelkező, angolul jól tudó programozóknak (a szótárral azonban nem lesz nagy probléma) és csak bővíteni akarják a látókörüket;

https://zserge.wordpress.com/2012/02/23/lua-in-60-minutes/ - a Lua alapjai 60 percben egy programozótól, akinek nyilvánvalóan nem közömbös ez a nyelv. Oroszul;

http://lua-users.org/wiki/LuaTutorial - wiki oktatóanyag;

https://youtube.com/watch?v=yI41OL0-DWM- YouTube oktatóvideók, amelyek segítenek vizuálisan megérteni az IDE beállítását és a nyelv alapelveit.

Lua szkriptek

Egy Lua nyelven írt szkriptnek nincs olyan speciális funkciója, amelytől a végrehajtása elkezdődne. A szkript egyszerűen tekinthető parancsok (utasítások) halmazának, amely az első utasítástól kezdve végrehajtódik.

A szkript lehet nagyon egyszerű, csak egy parancsból áll, vagy nagyon összetett, több tíz, száz vagy akár több ezer utasítást is tartalmazhat. A következő utasításokat pontosvesszővel (;) lehet elválasztani. Ez a követelmény azonban nem kötelező, így az alábbi kód mindegyike helyes a szintaxis szempontjából:

Munka változókkal a Lua-ban

A változók az értékek tárolására szolgálnak a szkript végrehajtása során.

Változónevek Lua-ban

A Lua változónevei (azonosítói) bármilyen betűből, számból és aláhúzásjelből álló sorozatok lehetnek, amelyek nem számmal kezdődnek.

jegyzet

A Lua nyelv megkülönbözteti a kis- és nagybetűket, így az abc, Abc, ABC különböző nevek.

Az alábbi táblázat a Lua nyelv által fenntartott szavakat sorolja fel, és nem használhatók változónevekben:

és törj mást csinálj

vége false if függvénynek

helyi nullában nem ill

ismételje meg a visszatérést, majd igaz, amíg

Ezenkívül minden olyan név le van foglalva, amely aláhúzással és nagybetűvel kezdődik (például _VERSION).

Mik a Lua változói?

A Lua változói lehetnek globálisak vagy lokálisak. Ha egy változó nincs kifejezetten lokálisnak deklarálva, akkor globálisnak tekintendő.

Lua globális változók

Egy globális változó akkor jelenik meg, amikor az első értékét hozzárendeljük. Az első érték hozzárendelése előtt a globális változó elérése nullát eredményez.

MsgBox(tostring(g)) --> nil

MsgBox(tostring(g)) --> 1

A globális változó addig létezik, amíg a parancsfájl-végrehajtási környezet létezik, és elérhető minden, ebben a környezetben futó Lua-kód számára.

Szükség esetén explicit módon törölhet egy globális változót úgy, hogy egyszerűen nullára állítja.

g = 1 - hozzon létre egy g globális változót 1 értékkel

g = nil - távolítsa el a g globális változót

MsgBox(tostring(g)) --> nil

Az összes globális változó egy normál tábla mezője, az úgynevezett globális környezet. Ez a táblázat a _G globális változón keresztül érhető el. Mivel a globális környezet mezői mind globális változók (beleértve magát a _G-t is), akkor _G._G == _G.

Lua helyi változók

Minden helyi változót kifejezetten deklarálni kell a helyi kulcsszó használatával. A szkriptben bárhol deklarálhat egy helyi változót. A deklaráció tartalmazhat egy kezdőérték hozzárendelését a változóhoz. Ha nincs érték hozzárendelve, a változó nullát tartalmaz.

local a - deklarálja a lokális változót a

local b = 1 - deklarálja a b helyi változót, adjon hozzá 1 értéket

lokális c, d = 2, 3 - deklarálja a c és d helyi változókat, rendelje hozzá a 2 és 3 értékeket

A lokális változó hatóköre a deklaráció után kezdődik és a blokk végéig tart.

jegyzet

A változó hatóköre a programkód egy része, amelyen belül hozzáférhet az ebben a változóban tárolt értékhez.

A blokkolás jelentése:

vezérlőstruktúra test (if-then, else, for, while, ismétlés);

funkció test;

a do...end kulcsszavak közé zárt kódrészlet.

Ha egy helyi változó bármely blokkon kívül van definiálva, akkor annak hatóköre a szkript végéig terjed.

local i = 1 - az i változó helyi a szkripten belül

miközben én<= a do - цикл от 1 до 5

lokális a = i^2 - az a változó lokális a while cikluson belül

MsgBox(a) --> 1, 4, 9, 16, 25

MsgBox(a) -->

ha i > 5 akkor

lokális a - az a változó belül lokális akkor

MsgBox(a) --> 10

MsgBox(a) --> 5 (itt a globális a-ra hivatkozva)

lokális a = 20 - az a változó lokális belső do-end

MsgBox(a) --> 20

MsgBox(a) --> 5 (itt a globális a-ra hivatkozva)

jegyzet

Lehetőség szerint helyi változók használata javasolt a globálisak helyett. Ez elkerüli a globális névtér szennyezését, és jobb teljesítményt biztosít (mivel a helyi változókhoz való hozzáférés a Lua-ban valamivel gyorsabb, mint a globálisak elérése).

Lua adattípusok

Milyen adattípusokat támogat a Lua nyelv?

A Lua a következő adattípusokat támogatja:

1. Null (semmi). Egy változó értékének hiányának felel meg. Ezt a típust egyetlen érték képviseli, a nulla.

2. Logikai (logikai). Ez a típus tartalmazza a false (false) és true (igaz) értékeket.

Logikai műveletek végrehajtásakor a nulla értéket hamisként kezeljük. Az összes többi értéket, beleértve a 0-t és az üres karakterláncot, a rendszer igazként kezeli.

3. Szám (numerikus). Számértékek ábrázolására szolgál.

A numerikus állandóknak lehet egy opcionális törtrésze és egy opcionális decimális kitevője, amelyet az "e" vagy "E" karakterek határoznak meg. Egész szám numerikus állandók adhatók meg hexadecimálisan a 0x előtag használatával.

Példák az érvényes numerikus állandókra: 3, 3.0, 3.1415926, 314.16e-2, 0xff.

4. Húr (string). A karakterláncok ábrázolására szolgál.

A karakterlánc-értékek egy vagy kettős idézőjelbe zárt karaktersorozatként vannak megadva:

a = "ez egy karakterlánc"

b = "ez a második sor"

A dupla idézőjelbe zárt karakterláncok képesek értelmezni a "\" karakterrel kezdődő C-szerű escape szekvenciákat (fordított perjel):

\b (szóköz),

\n (soremelés),

\r (kocsi vissza);

\t (vízszintes lap),

\\ (fordított perjel);

\"" (kettős idézőjel);

\" (egy idézőjel).

jegyzet

Egy karakterláncban lévő karakter a kódjával is ábrázolható az escape szekvencia használatával:

ahol ddd egy legfeljebb három számjegyből álló sorozat.

Az idézőjelek mellett dupla szögletes zárójelek is használhatók karakterlánc meghatározására:

Ha egy karakterláncot kettős szögletes zárójelekkel definiál, akkor figyelmen kívül hagyhatja az összes escape szekvenciát, azaz a karakterlánc teljesen a leírtak szerint jön létre:

helyi a = [] in Lua]=]

Lesz egy kifejezés: "karakterlánc[] definíció a lua nyelvben"

5. Funkció (függvény). A Lua függvényei változókba írhatók, paraméterként átadhatók más függvényeknek, és függvények végrehajtása eredményeként visszaadhatók.

6. Táblázat (tábla). A táblázat a "kulcs" - "érték" párok halmaza, amelyeket a táblázat mezőinek vagy elemeinek nevezünk. Mind a kulcsok, mind a táblázat mezőértékei bármilyen típusúak lehetnek, kivéve a nullát. A tábláknak nincs fix mérete: bármikor tetszőleges számú elemet adhat hozzájuk.

Bővebben a "Táblázatok létrehozása Lua programban" című cikkben

7. Felhasználói adatok (felhasználói adatok). Ez egy speciális adattípus. Az ilyen típusú értékek nem hozhatók létre vagy módosíthatók közvetlenül Lua szkriptben.

A felhasználói adatok a szkript hívójában vagy a C nyelven írt könyvtárakban létrehozott új típusok megjelenítésére szolgálnak. Például a "CronosPRO" Lua kiterjesztés könyvtárai ezt a típust használják olyan objektumok megjelenítésére, mint például:

adatbankok (Bank osztály);

adatbázisok (Base osztály);

rekordok (Rekord osztály) stb.

8. Szál (szál). Megfelel a végrehajtás folyamatának. Ezek a szálak semmilyen módon nem kapcsolódnak az operációs rendszerhez, és kizárólag maga a Lua támogatja őket.

Hogyan állítsuk be a változó típusát a Lua-ban?

A Lua nem határozza meg kifejezetten a változó típusát. A változó típusát akkor állítjuk be, amikor a változóhoz értéket rendelünk. Bármely változóhoz tetszőleges típusú érték rendelhető (függetlenül attól, hogy korábban milyen típust tartalmazott).

a = 123 - az a változó típusszámmal rendelkezik

a = "123" - az a változó most string típusú

a = igaz – az a változó most logikai típusú

a = () - az a változó most táblázat típusú

jegyzet

A táblázat, függvény, szál és userdata típusú változók nem magát az adatot tartalmazzák, hanem a megfelelő objektumokra való hivatkozásokat tárolják. Hozzárendeléskor, függvénynek argumentumként való átadáskor és ennek eredményeként függvényből való visszatéréskor az objektumok nem másolódnak, csak a rájuk való hivatkozások másolódnak.

a = () - táblázat létrehozása. A táblázatra való hivatkozás az a változóba kerül

b = a - a b változó ugyanarra a táblázatra vonatkozik, mint a

a = 10 - az 1-es indexű táblázatelem 10-es értéket kap

MsgBox(b) --> "10"

MsgBox(a) --> "20"

A többi adat azonnali érték.

MsgBox(a) --> "20"

MsgBox(b) --> "10"

Hogyan szerezhető be egy változó típusa a Lua-ban?

A változóban tárolt érték típusát a szabványos függvénytípus segítségével lehet megtudni. Ez a függvény egy karakterláncot ad vissza, amely tartalmazza a típus nevét ("nulla", "szám", "karakterlánc", "logikai", "tábla", "függvény", "szál", "felhasználói adatok").

t = type("ez egy karakterlánc") - t egyenlő a "karakterlánc"-val

t = típus(123) - t "szám"

t = típus(típus) - t egyenlő a "függvénnyel"

t = típus(igaz) - t "boolean"

t = típus(nil) - t "nil"

t = típus(CroApp.GetBank()) - t egyenlő a "felhasználói adatok"

Hogyan lehet átalakítani egy változó típusát a Lua-ban?

A Lua automatikusan karakterláncokká alakítja a számokat, és fordítva, ha szükséges. Például, ha egy karakterlánc-érték egy aritmetikai művelet operandusa, akkor a rendszer számmá alakítja. Hasonlóképpen, egy olyan numerikus értéket, amelynél egy karakterláncot várunk, a rendszer karakterláncsá alakítja.

a = "10" + 2 - a egyenlő 12-vel

a = "10" + 2 - a egyenlő "10 + 2"

a = "-5.3e-10"*"2" - a egyenlő -1.06e-09

a = "karakterlánc" + 2 - Hiba! A "karakterlánc" nem konvertálható számmá

Bármilyen típusú érték kifejezetten karakterláncsá konvertálható a szabványos tostring függvény segítségével.

a = tostring(10) - a értéke "10"

a = tostring(true) - a egyenlő az "igaz"-val

a = tostring(nil) - a egyenlő "nil"

a = tostring (( = "ez az 1. mező")) - a egyenlő a következővel: "tábla: 06DB1058"

Az előző példából láthatja, hogy a táblák tartalmát nem konvertálja a tostring függvény. Ezt az átalakítást a render függvény segítségével lehet végrehajtani.

a = render(10) - a értéke "10"

a = render(igaz) - a egyenlő az "igaz"-val

a = render(nil) - a "nil"

a = render (( = "ez az 1. mező")) - a jelentése "( = "ez az 1. mező")"

Egy érték kifejezett számmá alakításához használhatja a szabványos tonumber függvényt. Ha az érték egy számmá alakítható karakterlánc (vagy már szám), akkor a függvény az átalakítás eredményét adja vissza, ellenkező esetben nullát ad vissza.

a = tonumber("10") - a egyenlő "10"

a = toszám("10"..5") - a egyenlő 10,5

a = szám(igaz) - a egyenlő "nulla"

a = szám (nulla) - a egyenlő "nulla"

A megjegyzések elrendezése Lua nyelven

A Lua nyelvű megjegyzés két mínuszjellel (--) kezdődik és a sor végéig tart.

helyi a = 1 - egysoros megjegyzés

Ha két nyitó szögletes zárójel ([[) közvetlenül követi a "--" karaktereket, akkor a megjegyzés többsoros és a két záró szögletes zárójelig (]] folytatódik).

helyi a = 1 - [[ többsoros

egy komment ]]

A megjegyzésekben lévő dupla zárójelek egymásba ágyazhatók. Az összetévesztés elkerülése érdekében a zárójelek közé egyenlőségjel (=) kerül:

helyi a = [[Kronos Company]] - [=[

helyi a = [[Kronos Company]]

A "=" karakterek száma határozza meg a beágyazást:

local a = [=[valamilyen karakterlánc [] meghatározása a Lua-ban]=] --[==[

local a = [=[valamilyen karakterlánc [] meghatározása a Lua-ban]=]

A Lua-ban használt műveletek

A Lua nyelven írt kifejezésekben a következő típusú műveletek használhatók:

1. Aritmetikai műveletek.

A Lua a következő aritmetikai műveleteket támogatja:

+ (kiegészítés);

- (kivonás);

* (szorzás);

/ (osztály);

^ (hatványozás);

% (az osztás maradéka).

jegyzet

Az aritmetikai műveletek számokra és karakterláncokra egyaránt alkalmazhatók, amelyek ebben az esetben számokká alakulnak.

2. Összehasonlítási műveletek.

A következő érték-összehasonlítási műveletek engedélyezettek a Lua-ban:

== (egyenlő);

~= (nem egyenlő);

< (меньше);

> (nagyobb);

<= (меньше или равно);

>= (nagyobb vagy egyenlő).

jegyzet

Az összehasonlító műveletek mindig igaz vagy hamis logikai értéket adnak vissza.

A számok karakterláncokká alakításának szabályai (és fordítva) nem működnek az összehasonlítás során, azaz a "0" == 0 kifejezés hamis eredményt eredményez.

3. Logikai műveletek.

A logikai műveletek a következők:

és (logikai ÉS).

Az and operátor visszaadja az első operandust, ha hamisra vagy nullára értékeli. Ellenkező esetben a művelet a második operandust adja vissza (és ez az operandus bármilyen típusú lehet).

a = (nulla és 5) - a egyenlő nullával

a == (hamis és 5) - a hamis

a == (4 és 5) - a egyenlő 5-tel

vagy (logikai VAGY).

A vagy operátor az első operandust adja vissza, ha az nem hamis vagy nulla, ellenkező esetben a második operandust adja vissza.

a == (4 vagy 5) - a egyenlő 4-gyel

a == (hamis vagy 5) - a egyenlő 5-tel

jegyzet

A logikai műveletek és és/vagy bármilyen típusú értéket visszaadhatnak.

A logikai műveletek és vagy csak akkor értékelik ki a második operandus értékét, ha vissza kell adni. Ha nem szükséges, a második operandus nem kerül kiértékelésre. Például:

a == (4 vagy f()) - az f() függvény nem kerül meghívásra

nem (logikai NEM).

A not operátor mindig igaz vagy hamis értéket ad vissza.

4. Összefűzés művelete.

A karakterláncok összefűzéséhez (összevonásához) használja a ... műveletet (két pont).

a = "Kronos".."-".."Inform" - az a változó a "Kronos-Inform" értéket kapja

jegyzet

Ha az egyik vagy mindkét operandus szám, akkor azokat karakterláncokká alakítja a rendszer.

a = 0..1 - az a változó "01" értéket kap

5. A hossz megszerzésének művelete.

A Lua meghatározza a # hosszúságú operátort, amellyel egy karakterlánc hosszát kaphatjuk meg.

a = "karakterlánc"

len = #a - len egyenlő 6-tal

len = #"még egy sor" - a len 10

jegyzet

A # operátor segítségével megtudhatja egy tömb maximális indexét (vagy méretét). További részletekért olvassa el a „Tömbök használata Lua-ban” című cikket.

Üzemeltetői elsőbbség Lua-ban

A Lua-ban a műveletek a következő prioritás szerint kerülnek végrehajtásra (csökkenő sorrendben):

2. nem # - (egyetlen)

6. < > <= >= ~= ==

Szkriptek hívása űrlapokból

Minden űrlaphoz (beleértve a beágyazott űrlapokat is) külön szkript tartozik, amely általában olyan függvényeket tartalmaz, amelyek az űrlap és elemei eseményeit kezelik.

Egy űrlap futtatásakor a szkript betöltődik a globális környezetbe. Amikor egy űrlap vagy eleme eseménye bekövetkezik, a rendszer meghívja az eseményhez társított kezelő függvényt.

Meg kell jegyezni, hogy az űrlapszkript, bár nem tartalmazza a modul függvény hívását, valójában egy modul. Ez azt jelenti, hogy az űrlapszkriptben a helyi kulcsszó nélkül deklarált változók nincsenek kitéve a globális környezetnek, és csak ezen a szkripten belül érhetők el. Ha egy értéket más űrlapszkriptek számára is elérhetővé kell tenni, akkor azt kifejezetten meg kell adni a globális _G táblában:

local a = _G.var

Kijelentésblokkok (utasítások)

A fő Lua operátorok a következők:

feladat;

feltételes operátor;

üzemeltetők a ciklusok szervezéséhez.

Az utasítások egy csoportja blokkba (összetett utasítás) kombinálható a do...end konstrukcióval.

do - a blokk eleje

<оператор1>- blokktest

<оператор2>

<операторN>

vége - a blokk vége

A blokk új hatókört nyit meg, ahol helyi változókat definiálhat.

a = 5 - globális változó a

local a = 20 - az a helyi változó a do-end belsejében van definiálva

MsgBox(a) --> 20

MsgBox(a) --> 5 (itt a hivatkozás már a globális a)

Hozzárendelési operátor Lua nyelven

Egy hozzárendelés megváltoztatja egy változó vagy táblázat mező értékét. A legegyszerűbb formájában egy feladat így nézhet ki:

a = 1 - az a változóhoz 1 értéket rendelünk

a = b + c - az a változóhoz a b és c változók értékeinek összege van hozzárendelve

a = f(x) - az a változóhoz az f(x) függvény által visszaadott érték van hozzárendelve

A Lua-ban megengedett az úgynevezett többszörös hozzárendelés, amikor a hozzárendelési operátortól balra lévő több változó több, a hozzárendelési operátortól jobbra írt kifejezés értékét kapja:

a, b = 1, 5*c - a egyenlő 1; b egyenlő 5*c-vel

Ha több változó van, mint érték, az "extra" változók nullát kapnak.

a, b, c = 1, 2 - a egyenlő 1; b értéke 2; c egyenlő nullával

Ha több érték van, mint változó, akkor az „extra” értékek figyelmen kívül maradnak.

a, b = 1, 2, 3 - a egyenlő 1; b értéke 2; a 3. érték nem használt

Több hozzárendelés is használható a változók közötti értékek cseréjéhez:

a = 10; b = 20 – a értéke 10, b értéke 20

a, b = b, a - most a értéke 20, b értéke 10

Feltételes kijelentés (ha) a Lua nyelvben

Az if utasítás egy adott feltétel igazságtartalmát teszteli. Ha a feltétel igaz, akkor a kód akkor kulcsszót követő része (majd szakasz) végrehajtásra kerül. Ellenkező esetben az else kulcsszót követő kód (else section) végrehajtásra kerül.

ha a > b akkor

return a - ha a nagyobb, mint b, visszatér a a

return b - egyébként, return b

Az Egyéb rész nem kötelező.

Ha egy< 0 then

a = 0 – ha a kisebb, mint 0, állítsa a-t 0-ra

A beágyazott if utasítások helyett használhatja az elseif konstrukciót. Például a következő kód:

könnyebben olvasható lesz, ha a következőre cseréli:

adja vissza az "Ivánt" - ha a egyenlő 1-gyel

elseif a == 2 akkor

adja vissza "Péter"-t - ha a 2

elseif a == 3 akkor

adja vissza "Szergej"-t - ha a egyenlő 3-mal

adja vissza a „Nincs ilyen játékos” kifejezést – ha a egyik sem szerepel a listán

Hurok előfeltétellel (míg) Lua-ban

A while utasítás ciklusok szervezésére szolgál előfeltétellel, és a következő formájú:

míg csináld

... - huroktest

A ciklus minden iterációja előtt a feltételt ellenőrizzük :

ha a feltétel hamis, a ciklus véget ér, és a vezérlés átkerül a while utasítást követő első utasításra;

ha a feltétel igaz, akkor a ciklus törzse végrehajtódik, majd minden művelet megismétlődik.

míg i > 0 do - hurok 10-ről 1-re

t[i] = "mező"..i

a = (3, 5, 8, -6, 5)

míg i > 0 do - keressen negatív értéket a tömbben

ha a[i]< 0 then break end - если найдено, прерываем цикл

i = i - 1 - ellenkező esetben ugorjon a következő elemre

ha i > 0 akkor

MsgBox("Negatív érték index: "..i)

MsgBox("A tömb nem tartalmaz negatív értékeket")

jegyzet

Hurok utófeltétellel (ismétlés) Lua nyelven

Az ismétlő operátort úgy tervezték, hogy ciklusokat szervezzen utófeltétellel, és a következő formájú:

... - huroktest

amíg

A ciklus törzse a feltételig végrehajtódik nem lesz igaz. A feltétel a ciklustörzs végrehajtása után kerül ellenőrzésre, így minden esetben a ciklustörzs legalább egyszer végrehajtásra kerül.

Addig összegezzük az a tömb értékeit, amíg az összeg nem haladja meg a 10-et

a = (3, 2, 5, 7, 9)

összeg = összeg + a[i]

amíg összeg > 10

MsgBox("Hozzáadott ..i.." elemek. Sum egyenlő "..sum")

A break utasítással kitörhet a ciklusból, mielőtt az véget ér.

jegyzet

A break utasítás használatának funkcióiról további információért olvassa el a „Break and return utasítások” című cikket.

Cikkek egy for utasítással a Lua nyelvben

A for utasítás ciklusok rendszerezésére szolgál, és kétféle írást tesz lehetővé:

egyszerű (numerikus for);

kiterjesztett (univerzális for).

A for utasítás egyszerű formája

A for utasítás egyszerű formája a következő:

for var = exp1, exp2, exp3 do

... - huroktest

A ciklustörzs a var hurokváltozó (számláló) minden értékére lefut az exp1 és exp2 tartományban, exp3 lépéssel.

jegyzet

Lehetséges, hogy a lépés nincs megadva. Ebben az esetben ez egyenlő 1-gyel.

ha i = 1, 10 do - hurok 1-ről 10-re az 1. lépéssel

MsgBox("i egyenlő"..i)

ha i = 10, 1, -1 do - hurok 10-ről 1-re a -1 lépéssel

MsgBox("i egyenlő"..i)

jegyzet

Az exp1, exp2 és exp3 kifejezések csak egyszer kerülnek kiértékelésre, a ciklus kezdete előtt. Tehát az alábbi példában az f(x) függvény csak egyszer lesz meghívva a hurok felső határának kiszámításához:

ha i = 1, f(x) do - hurok 1-ről az f() által visszaadott értékre

MsgBox("i egyenlő"..i)

A ciklusváltozó lokális a ciklusutasításhoz, és nincs megadva a ciklus végén.

ha i = 1, 10 do - hurok 1-ről az f() által visszaadott értékre

MsgBox("i egyenlő"..i)

MsgBox("A ciklusból való kilépés után az i "..i") - Rossz! egyenlő vagyok a nullával

jegyzet

Egy ciklusváltozó értéke nem változtatható meg a cikluson belül: egy ilyen változás következményei megjósolhatatlanok.

A break utasítás a ciklusból való kilépésre szolgál, mielőtt az befejeződik.

a = (3, 5, 8, -6, 5)

ha i = 1,#a do - keressen negatív értéket a tömbben

ha a[i]< 0 then - если найдено...

index = i - a talált érték indexének mentése...

megtörni – és megtörni a hurkot

MsgBox("Negatív érték index: "..index)

jegyzet

A break utasítás használatának funkcióiról további információt a „Break and return utasítások” című cikkben talál.

Szentimentális programozó vagyok. Néha beleszeretek a programozási nyelvekbe, aztán órákig tudok róluk beszélni. Egy ilyen órát megosztok veletek.

lua? Mi ez?

A Lua egy egyszerű beágyazható nyelv (integrálható más nyelven írt programjaival), könnyű és érthető, egyetlen adattípussal, egységes szintaxissal. A tökéletes nyelv a tanuláshoz.

Minek?

A Lua hasznos lehet az Ön számára:

* ha játékos vagy (plugin a World of Warcrafthoz és sok más játékhoz)
* Ha játékokat ír (nagyon gyakran a játékokban, a motor C / C ++, és AI - Lua nyelven van írva)
* ha Ön rendszerprogramozó (írhat bővítményeket az nmap, a wireshark, az nginx és más segédprogramokhoz a Lua-ban)
* ha Ön beágyazott fejlesztő (a Lua nagyon gyors, kompakt és nagyon kevés erőforrást igényel)

1. Tanulj meg programozni. Legalább egy kicsit. Nem mindegy milyen nyelven.
2. Telepítse a Lua-t. Ehhez töltse le az 5.2-es verziót innen (http://www.lua.org/download.html), vagy keresse meg a tárolókban. Az 5.1-es verzió is működni fog, de vegye figyelembe, hogy nagyon régi.

Futtassa a cikk összes példáját a terminálban egy olyan paranccsal, mint a „lua file.lua”.

Első benyomások

A Lua egy dinamikusan tipizált nyelv (a változók a hozzárendelt értékektől függően menet közben kapnak típusokat). Írhatsz rá felszólító és objektum-orientált vagy funkcionális stílusban is (még ha nem is tudod, hogy van, nem baj, olvass tovább). Íme a Hello világ Luában:

Az első lua alkalmazásom: hello.lua nyomtatott "hello world"; print ("viszlát világ")

Mit mondhatunk a nyelvről:

* Az egysoros megjegyzések két kötőjellel "--" kezdődnek
* a zárójelek és pontosvesszők elhagyhatók

Nyelvi operátorok

A feltételes utasítások és ciklusok halmaza meglehetősen jellemző:

Feltételes utasítások (nem lehet else ág) if a == 0 then print("a nulla") else print("a nem nulla") end -- rövid alak if/elseif/end (a switch/ helyett case) if a == 0 then print("nulla") elseif a == 1 then print("egy") elseif a == 2 then print("kettő") else print("egyéb") end -- count ciklus ha i = 1, 10 do print(i) vége -- ciklus b = 5 előfeltétellel, míg b > 0 do b = b - 1 vége -- ciklus utófeltétellel ismételje meg a b = b + 1-et addig, amíg b >= 5

GONDOLJON MEG: mit jelenthet a "for i = 1, 10, 2 do ... end" ciklus?

A kifejezésekben a következő operátorokat használhatja a változókhoz:

* hozzárendelés: x = 0
* aritmetika: +, -, *, /, % (maradék), ^ (hatványozás)
* logikus: és, vagy, nem
* összehasonlítás: >,<, ==, <=, >=, ~= (nem egyenlő, igen-igen, a szokásos "!=" helyett)
* karakterlánc összefűzés (operátor ".."), pl.: s1="hello"; s2="világ"; s3=s1..s2
* hossz/méret (# operátor): s="hello"; a = #s ('a' egyenlő lesz 5-tel).
* elem beszerzése index szerint, pl.: s

A nyelvben sokáig nem voltak bitműveletek, de az 5.2-es verzióban megjelent a bit32-es könyvtár, ami ezeket megvalósítja (függvényként, nem operátorként).

Adattípusok

Hazudtam neked, amikor azt mondtam, hogy a nyelvnek egy adattípusa van. Rengeteg ilyen van benne (mint minden komoly nyelv):

* nulla (egyáltalán semmi)
* logikai számok (igaz/hamis)
* számok (számok) - egész számokra osztás nélkül / valós. Csak számok.
* karakterláncok - egyébként nagyon hasonlítanak a pascal karakterláncaira
* függvények - igen, a változó lehet "function" típusú
* cérna
* tetszőleges adat (felhasználói adatok)
* asztal

Ha minden világos az első típusoknál, akkor mi az a userdata? Emlékezzünk vissza, hogy a Lua egy beágyazható nyelv, és általában szorosan együttműködik más nyelveken írt programösszetevőkkel. Tehát ezek az "idegen" komponensek saját igényeik szerint hozhatnak létre adatokat, és tárolhatják ezeket az adatokat a lua objektumokkal együtt. Tehát a userdata a jéghegy víz alatti része, amelyre a lua nyelv szempontjából nincs szükség, de egyszerűen nem hagyhatjuk figyelmen kívül.

És most a legfontosabb dolog a nyelvben - táblázatok.

táblázatok

Megint hazudtam, amikor azt mondtam, hogy a nyelvnek 8 adattípusa van. Gondolhatod, hogy ez egy: minden táblázat (ez egyébként szintén nem igaz). A tábla egy nagyon elegáns adatstruktúra, egyesíti egy tömb, egy hash tábla ("kulcs" - "érték"), egy struktúra, egy objektum tulajdonságait.

Tehát itt van egy példa egy táblázatra mint tömbre: a = (1, 2, 3) -- egy 3 elemből álló tömb print(a) -- "2"-t ír ki, mert az indexeket egytől számítják -- És a táblázat ritka tömb formájú (amelynek nincs minden eleme) a = () -- üres tábla a = 1 a = 5

GONDOLJON MEG: mi az a ritka tömb esetén?

A fenti példában a táblázat tömbként viselkedik, de a valóságban kulcsaink (indexek) és értékeink (tömbelemek) vannak. Ugyanakkor a billentyűk bármilyen típusúak lehetnek, nem csak számok:

A = () a["hello"] = igaz a["világ"] = hamis a = 1 -- vagy így: a = ( hello = 123, world = 456 ) print(a["hello")) print ( a.hello) ugyanaz, mint a ["hello"], bár úgy néz ki, mint egy mezős szerkezet

Egyébként, mivel a táblázatnak vannak kulcsai és értékei, ismételheti az összes kulcsot és a hozzájuk tartozó értékeket egy ciklusban:

T = ( a = 3, b = 4 ) kulcs esetén, érték párban(t) do print(kulcs, érték) -- "a 3"-t, majd "b 4"-et ír ki

De mi a helyzet a tárgyakkal? Róluk egy kicsit később fogunk tanulni, először a funkciókról.

Funkciók

Íme egy példa egy szabályos függvényre.

Függvény add(a, b) return a + b end print(add(5,3)) -- print "8"

A nyelvi függvények lehetővé teszik több argumentum felvételét és több argumentum visszaadását. Tehát azokat az argumentumokat, amelyek értéke nincs kifejezetten megadva, nullával egyenlőnek tekintjük.

GONDOLJON: miért szeretne több argumentumot visszaadni?

A swap(a, b) függvény visszaadja b, a vége x, y = swap(x, y) -- ez egyébként függvény nélkül is megoldható: x, y = y, x -- és ha a függvény visszaad több argumentum, -- nincs szükség rájuk - figyelmen kívül hagyja őket a -- speciális "_" aláhúzás változóval a, _, _, d = some_function()

A függvények változó számú argumentumot vehetnek fel:

A prototípusban változó számú argumentum ellipszis függvényként van írva: sum(...) s = 0 _ esetén, n párban(arg) do -- a függvényben ezek "arg" s = s táblázatként érhetők el. + n end return a end sum(1, 2, 3) -- 6-ot ad vissza sum(1, 2, 3, 4) -- 10-et ad vissza

Mivel a függvények teljes értékű adattípusok, létrehozhat függvényváltozókat, vagy átadhat függvényeket argumentumként más függvényeknek.

A = függvény(x) visszatér x * 2 vége -- 2-vel szorzó függvény b = függvény(x) visszatér x + 1 vége -- 1-gyel növekvő függvény vonatkozik (táblázat, f) eredmény = () k esetén, v párokban(táblázatban) csináld az eredményt[k] = f(v) -- cseréld ki az elemet ennek az elemnek valamilyen függvényével vége vége -- GONDOLKODJ: a t = (1, 3, 5) hívások érvényesek(t, a) alkalmaz(t,b)

Objektumok = függvények + táblák

Mivel a függvényeket változókban tárolhatjuk, ezért táblamezőkben is tárolhatjuk. És máris kiderül, mintha-módszerek. Aki nem ismeri az OOP-ot, annak elmondom, hogy a fő előnye (legalábbis Lua-ban) az, hogy a funkciók és az általuk kezelt adatok a közelben vannak - ugyanazon az objektumon belül. Azok számára, akik ismerik az OOP-t, elmondom, hogy itt nincsenek osztályok, és prototípus öröklődés.

Térjünk át a példákra. Van egy tárgyunk, mondjuk egy villanykörte. Tudja, hogyan kell égetni és nem égetni. Nos, két műveletet végezhet vele – kapcsolja be és ki:

Lamp = ( be = false ) függvény turn_on(l) l.on = true end függvény turn_off(l) l.on = false end -- ezek csak a turn_on(lamp) turn_off(lamp) szerkezettel való munkavégzés függvényei

És ha a villanykörtét objektummá tesszük, a turn_off és turn_on függvényeket pedig az objektum mezőivé, akkor a következőt kapjuk:

Lámpa = ( be = false turn_on = function(l) l.on = true end turn_off = function(l) l.on = false end ) lamp.turn_on(lamp) lamp.turn_off(lamp)

Első érvként kénytelenek vagyunk átadni magát a villanykörte objektumot, mert különben a funkciónk nem fogja tudni, hogy melyik izzóval dolgozzon a be/ki állapot megváltoztatásához. De hogy ne legyen bőbeszédű, a Lua-nak van egy általában használt rövidítése - lamp:turn_on (). Összességében már több ilyen szintaktikai egyszerűsítést ismerünk:

lamp:turn_on() -- a leggyakoribb jelölés lamp.turn_on(lamp) -- ez szintaktikai szempontból is helyes lamp["turn_on"](lámpa) -- és ez

Továbbra is a rövidítésekről beszélünk, a függvények nem csak kifejezetten, mint egy struktúra mezői írhatók le, hanem kényelmesebb formában is:

Lamp = ( on = false ) -- ponton keresztül, akkor az argumentumot meg kell adni a lamp.turn_on(l) l.on = true end függvényt -- kettősponton keresztül, ekkor az argumentum implicit módon be van állítva, mint a "self" változó " -- "self" - és van az a villanykörte, amelynél a lamp:turn_off() metódus self.on = false end

Érdekes?

Különleges képességek

Egyes táblafüggvénynevek (metódusok) le vannak foglalva, és különleges jelentéssel bírnak:

* __add(a, b), __sub(a, b), __div(a, b), __mul(a, b), __mod(a, b), __pow(a, b) - számtani műveletek végrehajtásakor hívódnak meg asztalon
* __unm(a) - unáris művelet "mínusz" (amikor olyasmit írnak, mint "x = -x")
* __lt(a, b), __le(a, b), __eq(a, b) - kiszámítja az összehasonlítási eredményt (<, <=, ==)
* __len(a) - akkor hívják meg, ha az "#a" kész
* __concat(a, b) - az "a..b" hívása
* __call(a, …) — az "a()"-ra hívják. A változó argumentumok meghívásakor argumentumok
* __index(a, i) - hozzáférés az a[i]-hez, feltéve, hogy ilyen elem nem létezik
* __newindex(a, i, v) - "a[i] = v" létrehozása
* __gc(a) - amikor egy objektumot eltávolítanak a szemétgyűjtéssel

Ezen metódusok felülbírálásával túlterhelheti az operátorokat, és saját céljaira használhatja a nyelv szintaxisát. A lényeg az, hogy ne vigyük túlzásba.

Öröklés

Azok számára, akik nem ismerik az OOP-t, az öröklődés lehetővé teszi egy már meglévő osztály funkcionalitásának kiterjesztését. Például csak egy villanykörte tud be- és kikapcsolni, és egy szuper izzó is megváltoztatja a fényerejét. Miért kell átírnunk a turn_on/turn_off metódusokat, ha újra felhasználhatjuk őket?

A Lua-ban erre van egy meta-tábla fogalma, i.e. őstábla. Minden táblának van egy szülőtáblája, és a gyermektábla mindent megtehet, amit a szülő.

Tegyük fel, hogy már elkészítettük a lámpaasztal objektumot. Akkor a szuperizzó így fog kinézni:

Szuperlámpa = ( fényerő = 100 ) -- adja meg a szülőtáblázatot, metatable (szuperlámpa, lámpa) -- és a metódusai már elérhetőek superlamp:turn_on() superlamp:turn_off()

Funkcióbővítés

Sok típusnak van szülőtáblája (na jó, karakterláncok és táblák biztosan, számok és logikai értékek, a nullánál pedig nincs ilyen). Tegyük fel, hogy az összes karakterláncot a "+" operátorral szeretnénk hozzáadni, nem a ".." karakterláncot. Ehhez le kell cserélni a "+" (__add) függvényt az összes sor szülőtáblájában:

S = getmetatable("") -- a sor szülőtáblájának lekérése s.__add = function(s1, s2) return s1..s2 end -- metódus módosítása -- check a = "hello" b = "world" print(a + b) -- írja be: "helloworld"

Valójában a print függvényt továbbra is lecserélhetjük a "print = myfunction"-ra, és sok más durva dolgot is meg lehet tenni.

Hatókör

A változók globálisak vagy lokálisak. Létrehozásakor a Lua összes változója globális.

GONDOLKODJ: miért?

A helyi hatókör meghatározásához írja be a helyi kulcsszót:

Helyi x helyi var1, var2 = 5, 3

Ne felejtsd el ezt a szót.

Hiba a feldolgozásban

Ha hibák lépnek fel, gyakran le kell állítani egy bizonyos funkció végrehajtását. Természetesen sok ellenőrzést végezhet, és felhívhatja a "return"-ot, ha valami hiba történt. De ez növeli a kód mennyiségét. A Lua valami kivételt használ.

A hibák az error(x) függvény segítségével generálódnak. Bármi átadható argumentumként (ami a hibához kapcsolódik - karakterláncleírás, numerikus kód, objektum, amellyel hiba történt, stb.)

Általában e funkció után az egész program összeomlik. És ez nem mindig szükséges. Ha olyan függvényt hív meg, amely hibát okozhat (vagy az utódfüggvényei okozhatnak hibát), akkor hívja meg biztonságosan a pcall() segítségével:

Függvény f(x, y) ... if ... then error("valamit nem sikerült megcsinálni") end ... vége állapot, err = pcall(f, x, y) -- f: függvény, xy: annak argumentumok, ha nem állapot, akkor -- kezelési hiba hiba. Esetünkben az err az end hibaszöveget tartalmazza

Szabványos könyvtárak

Sok nem szabványos könyvtár létezik, ezek megtalálhatók a LuaForge, LuaRocks és más tárhelyeken.

Lua és nem Lua között

De mi van akkor, ha a szabványos könyvtárak funkcionalitása nem elegendő számunkra? Mi van akkor, ha megvan a C programunk, és Lua-ból szeretnénk meghívni a függvényeit? Ennek egy nagyon egyszerű mechanizmusa van.

Tegyük fel, hogy szeretnénk létrehozni egy saját függvényt, amely egy véletlen számot ad vissza (Lua rendelkezik math.random(), de szeretnénk megtanulni. A következő C kódot kell írnunk:

#beleértve #beleértve #beleértve /* valójában mit kell tenni a `rand(from, to)` meghívásakor */ static int librand_rand(lua_State *L) ( int from, to; int x; from = lua_tonumber(L, 1); /* első függvényparaméter * / to = lua_tonumber(L, 2); /* második függvényparaméter */ x = rand() % (to - from + 1) + from; lua_pushnumber(L, x); /* visszatérési érték */ return 1; / * csak egy argumentumot ad vissza */ ) /* a Lua "rand"-ban a librand_rand() függvényünknek felel meg */ static const luaL_reg R = (("rand", librand_rand), (NULL, NULL) /* az exportált termékek listájának vége függvények */ ); /* meghívva a könyvtár betöltésekor */ LUALIB_API int luaopen_librand(lua_State *L) ( luaL_openlib(L, "librand", R, 0); srand(time(NULL)); return 1; /* sikeres */ )

Azok. A Lua olyan függvényeket biztosít számunkra, amelyek segítségével adattípusokkal dolgozhatunk, függvényargumentumokat vehetünk fel és eredményeket adhatunk vissza. Nagyon kevés funkció van, és nagyon egyszerűek. Most dinamikusként építjük fel a könyvtárunkat, és használhatjuk a rand() függvényt:

Véletlenszerű = követelmény("librand") -- a könyvtár betöltése print(random.rand(1, 100)) print(random.rand(0, 1))

Mi van, ha Lua kódot akarunk hívni a programjainkból? Ezután a programjainknak létre kell hozniuk egy Lua virtuális gépet, amelyen a Lua szkriptek végrehajtásra kerülnek. Sokkal egyszerűbb:

#include "lua.h" #include "lauxlib.h" int main() ( lua_State *L = lua_open(); // létrehozza a Lua virtuális gépet luaL_openlibs(L); // betölti a szabványos könyvtárakat luaL_dofile(L, " rand. lua"); // a lua_close(L) parancsfájl végrehajtása; // a Lua return 0 bezárása; )

Minden.

Most már írhat Lua nyelven. Ha érdekes dolgokat tud meg Luáról, amelyek tükröződhetnek a cikkben - írjon!

Ebben az általam kidolgozott oktatóanyag-sorozatban a Lua programozási nyelvről lesz szó. Igyekszem a prezentációt a kezdők számára is minél elérhetőbbé tenni, és rájuk fogok koncentrálni. Vagyis a tapasztalt Lua kódolók nagy valószínűséggel nem tanulnak innen semmi újat (biztos vagyok benne, hogy itt csak a szedésnek és a kommenteknek találnak helyet, amiket tulajdonképpen még szívesen is fogadnak a részükről), de ha nincs gazdag programozási tapasztalatod a hátad mögött, akkor azt hiszem, kapsz valamit.

Az egész sorozat nem fog engedelmeskedni semmilyen rendszernek. A leckék szekvenciálisan bevezetnek egy sor nyelvi konstrukciót, így a harmadik vagy negyedik órán már meg tudod írni a programjaidat. Az a célom, hogy rábírjalak arra, hogy önállóan tanuld a nyelvet, segítsek érezni, nem pedig elmagyarázni A-tól Z-ig - ha teljesen el akarod sajátítani a nyelvet, olvasd el a kézikönyvet (ami, ha rosszul is, de le van fordítva oroszul: http://www.lua .ru/doc/). Minél hamarabb vált át a weben található „for dummies” oktatóanyagokról a kézikönyvre, annál jobb.

Ha valami nem világos - feltétlenül tegyen fel kérdést a megjegyzésekben, és én és a többi résztvevő megpróbálunk segíteni.

A Lua egy népszerű, könnyen megtanulható, általános célú, beágyazható, értelmezhető, dinamikusan tipizált programozási nyelv. Nem, nem kell megértenie az előző mondat szavainak felét sem - a lényeg az, hogy tudd, hogy népszerű és egyszerű. Egyébként az egyszerűség, valamint a disztribúció kis mérete (kb. 150 kilobájt) megérdemelte a népszerűségét. A Lua szkripteket számos alkalmazás támogatja, beleértve a játékokat is. A World of Warcraft és a S.T.A.L.K.E.R. használja a Lua nyelvet. Kedvenc játékmotorom lehetővé teszi, hogy könnyedén létrehozz különféle játékokat a Lua segítségével. Amint látja, a Lua sok távlatot nyit meg előtted!

Mielőtt elkezdené, be kell állítania egy programozási környezetet: vagyis keressen egy programot, amely veszi az Ön által írt Lua kódot és végrehajtja azt: egy értelmezőt. Itt három lehetőség van:

1. Töltse le a hivatalos Lua disztribúciót az azokat szállító webhelyek egyikéről.

A Lua hivatalos weboldaláról csak a tolmács forráskódja tölthető le. Ha azonban megnézi a http://lua.org/download.html címet a Binaries részben, akkor Windows végrehajtható fájlokat tartalmazó webhelyekre mutató hivatkozásokat találhat. Egyikük: . Töltsd le onnan az egyik archívumot (a platformodnak megfelelő: Win32 vagy Win64), és csomagold ki valahonnan, lehetőleg egy rövid elérési úttal rendelkező könyvtárba: például C:\lua. Mostantól azt feltételezem, hogy Windowst használ, és ott található a tolmács.

A Linux-alapú operációs rendszerek felhasználói ebben az értelemben könnyebben járnak: csak a csomagkezelőt kell használniuk, és telepíteni kell a Lua-t a tárolókból. Debian és Ubuntu esetén ez az apt-get install lua, Fedora, Red Hat és származékai esetén pedig a yum install lua segítségével történik. Azonban ne bízzon bennem vakon, és olvassa el az operációs rendszere kézikönyvét, hogy megtudja, pontosan hogyan történik ez az Ön számára.

2. Használjon online tolmácsot.

A következő címen található: http://www.lua.org/demo.html. Eleinte elég lehet, de a jövőben, amikor hozzáérünk a modulokhoz, kénytelen lesz az offline verziót használni. Az online tolmács használata nagyon egyszerű: írja be a programját a szövegmezőbe, és kattintson a Futtatás gombra. A program lefut, az Output ablakban megjelenik a programod kimenete, valamint Ön által készített hibajelentések, ha vannak.

3. Használjon IDE-t.

Például a ZeroBrane Studio: http://studio.zerobrane.com/. Vannak mások is – nézd meg a neten.

A Lua két, kissé eltérő verziója jelenleg használatban van: 5.1 és 5.2. A legújabb verzióra fogok összpontosítani - az 5.2-es verzióra, de ügyeljen arra, hogy rámutasson a lényeges különbségekre az 5.1 és az 5.1 között, mivel az utóbbi is meglehetősen gyakori. A Lua 5.1 egyébként másfélszer gyorsabban hajtja végre a kódot, mint a Lua 5.2, csak hogy tudd.

=== 1. lecke ===

Szóval, kezdjük. Hozzon létre egy main.lua fájlt egy idegen fájloktól elkülönített mappában, és írja be:

200?"200px":""+(this.scrollHeight+5)+"px");">
-- main.lua --
print ("Helló világ!")

Ezután futtassa a parancssorban (ne felejtsen el a main.lua könyvtárba lépni a cd paranccsal):

200?"200px":""+(this.scrollHeight+5)+"px");">
> C:\lua\lua.exe main.lua

Válaszul a Lua tolmács kiadja:

200?"200px":""+(this.scrollHeight+5)+"px");">
Helló Világ!

Alapvetően ez várható is. A programban a nyomtatási függvényt hívtuk. A nyomtatási funkció tetszőleges számú paramétert vesz fel, és sorban kinyomtatja a képernyőre. Ebben a példában a „Hello world!” karakterláncot (karakterláncot) adtuk át neki. Ugyanilyen sikerrel megadhatja paraméterként:

200?"200px":""+(this.scrollHeight+5)+"px");">
print(8) -- valamilyen decimális szám
-- kimenet: 8

Nyomtatás(0xDEADBEEF) -- hexadecimális szám
-- kimenet: 3735928559

Print("0xDEADBEEF") -- és ez egy karakterlánc, nem egy szám! Lásd az idézeteket?
-- nyomtat: 0xDEADBEEF

Nyomtatás (1,35e-4) -- lebegőpontos szám (tört)
-- Kimenetek 0,000135. Az 1,35e-4 úgy kell érteni, hogy "1,35-szer
- tízzel a mínusz negyedik hatványig", ha valaki nem tudná.

Print((198*99)-3*500 + 14/88) -- kifejezés
-- Megjeleníti a következő kifejezés értékét: 18102.159090909. Nem rossz alternatíva
-- egy asztali számológép!

Print(198/7, "műtrágya", 2^9) -- néhány tetszőleges paraméter
-- típus. Mindegyik értéke megjelenik, jelekkel elválasztva.
-- lapok:
-- 28.285714285714 műtrágya 512
-- Vegye figyelembe, hogy a műtrágya körüli idézőjeleket nem nyomtatjuk ki!

Nyomtatás(1,35) -- két szám, nem decimális 1,35!
-- A lehetőségek elválasztására vesszőt használunk.
-- Kimenetek:
-- 1 35

A „--” jel nem csupán egy kötőjel utánzata, amelyet a szépség kedvéért szúrnak be. A "--" jel a Lua-ban megjegyzéseket jelöl: olyan tippeket a programozó számára, amelyeket az értelmező figyelmen kívül hagy, és amelyek célja a kód könnyebb megértése. Megpróbálhatod beírni a programba:

200?"200px":""+(this.scrollHeight+5)+"px");">
--print("semmi")

A tolmács azt hiszi, hogy ez egy megjegyzés, és nem hajtja végre az utasítást.

Megjegyzés a háziasszonynak: ha csak egy sort szeretne nyomtatni, akkor a nyomtatási felhívást így írhatja meg, zárójelek nélkül:

200?"200px":""+(this.scrollHeight+5)+"px");">
nyomtatás "Csak egy karakterlánc"

A kényelem mindenképpen megkérdőjelezhető: ne feledje, hogy ez lehetséges. Az ilyen hívások azonban nem megengedettek:

200?"200px":""+(this.scrollHeight+5)+"px");">
print 2 nem fog működni, a 2 nem egy karakterlánc.
nyomtatás 2*2 + 6 -- annál inkább nem fog működni

Str = "karakterlánc!!" -- állítsa be az str változót "string!!
-- olvassa el a változókat alább
print str -- sem fog működni.

A fenti esetekben a program egyszerűen megtagadja a működést. Így egy "zárójel nélküli" hívásnál csak egy string literál (vagyis egy idézőjelbe zárt karaktersorozat) követheti a függvény nevét, semmi más. A jövőben kicsit részletesebben fogok beszélni erről a funkcióról, de egyelőre ennyi elég is.

Bármilyen jó programozási nyelvben lehetséges változók deklarálása: kis konténerek, amelyek tartalmazhatnak valamilyen adatot. Lua-ban ez így történik:

200?"200px":""+(this.scrollHeight+5)+"px");">
<имя_переменной> = <выражение>

Például:

200?"200px":""+(this.scrollHeight+5)+"px");">
csillag = 8 -- A csillag változó most a 8-as számot tárolja
wars = "owl" -- A wars változóban a "bagoly" karakterlánc
jedi = 42/2 -- A jedi változó a 21
luke = csillag*jedi -- A Luk változó a 168-as szám (igen, 21-szer 8)

A változók és a velük együtt járó kifejezések értékei is megjeleníthetők a képernyőn:

200?"200px":""+(this.scrollHeight+5)+"px");">
nyomtatás (csillag, háborúk, jedi, jedi-csillag+luke)
-- Kimenetek:
-- 8 bagoly 21 181

Csak ne próbálja meg hozzáadni a star and wars változókat – ha megpróbál 8-at hozzáadni a „bagolyhoz”, az nem tesz jót!

Amint azt észre kellett volna venni, egy változó neve szinte bármi lehet: a lényeg, hogy ne számmal kezdõdjön. Komolyan mondom, akár deklarálhatsz egy print nevű változót is és akkor a print funkció leáll, mert a print név az újonnan deklarált változóra fog hivatkozni. De van egy szócsoport, amelyet tilos változónévként használni - ezek olyan nyelvi kulcsszavak, amelyekkel még nem találkoztunk, de mindenképpen érdemes megnézni:

200?"200px":""+(this.scrollHeight+5)+"px");">
és törj csináld mást, ha vége
false a goto if in függvénynek
helyi nulla vagy ismételje vissza
akkor igaz mindaddig

Ha létrehoz egy ilyen nevű változót, akkor hibát fog okozni a programban, és az biztosan nem fog működni. Vegye figyelembe, hogy a Lua 5.1-ben nincs goto kulcsszó, és hívhat egy változót, de jobb, ha ezt nem teszi.
Vegye figyelembe azt is, hogy a változónevek megkülönböztetik a kis- és nagybetűket. Ez azt jelenti, hogy a foo, fOo, fOO és FOO négy különböző változó, tehát ha egy változónevet kisbetűvel írunk, később pedig nagybetűvel írjuk le, akkor a program nagy valószínűséggel nem fog megfelelően működni.

És most egy fontos kérdés: mi történik, ha véletlenül vagy szándékosan egy nem létező változóra hivatkozol? A legtöbb más nyelven ez hibát okoz, de Lua nyelven ez a helyzet elfogadható. Úgy kell kezelni, mintha egy nem létező változó valóban létezne, de az értéke igen nulla. nulla- Emlékezz erre a szóra! egy speciális értéktípus a lua nyelvben, ami azt jelenti, hogy "semmi". Nem nulla és nem üres karakterlánc (olyan karakterlánc, mint a "" - próbálja meg megjeleníteni a képernyőn), de egyszerűen semmi. Hasonlítsd össze ezzel a modellel: két ember van, az egyiknek van bankszámlája, de nincs pénze, a másiknak pedig egyáltalán nincs bankszámlája. A Lua szempontjából úgy kell tekinteni, hogy az első számláján 0 dollár van, a második számláján nulla. És még csak nem is dollár, hanem egyszerűen nulla. Remélem nem zavartalak meg.

Próbálkozzon például a következő programmal:

200?"200px":""+(this.scrollHeight+5)+"px");">
-- main.lua --
foo="bár"
nyomtatás (foo, baz)
-- Kimenetek:
-- bár nulla

Így a nem létező, de létezőnek feltételezett baz változó értéke nil, a print függvény ezt megérti és "nulla" karakterláncként írja ki a képernyőre. A Lua-nak van egy jó módszere a változó létezésének ellenőrzésére: ha egy változó értéke nem nulla, akkor legalább deklarálva van. Másrészt, kifejezetten deklarálhat egy nullával egyenlő változót:

200?"200px":""+(this.scrollHeight+5)+"px");">
cool_var = nulla

Ezt meg lehet tenni, és bár első pillantásra butaságnak tűnik, néha megteszik. A következő leckéken megtudhatod, ki és miért, és valószínűleg te is elkezded ugyanezt. Néha persze.
Legyen óvatos a nullával ": nullát írhat, de nem számolhat vele! Vagyis ha a print (null) megúszta, akkor egy 99 + nullához hasonló konstrukció hibát fog okozni, még akkor is, ha mint a 99+ nulla volt 99. Hidd el, én is ideges voltam, amikor megtudtam.

Összegzés:
1. Megismertük a nyomtatási funkciót, mit tud, és hogyan hívhatjuk helyesen zárójelek nélkül.
2. Megtanultuk, hogyan deklaráljunk változókat, hogyan értékeljünk kifejezéseket (bár eléggé), milyen nevek lehetnek a változóknak.
3. Megismertük a nullát, átitatva annak misztikus misztériumával, és megbizonyosodtunk arról, hogy a jövőben kapcsolatban leszünk vele.

Az érdeklődőknek, tudásukat erősíteni szeretnék, egyszerű gyakorlatokat ajánlok, ami kihagyható, ha már elég kompetensnek érzi magát:
1. Írj egy programot, amely kiírja kedvenc dalod refrénjét.
2. Próbálja megjeleníteni a következő kifejezések értékeit. Próbáld megérteni, hogy egyesek miért működnek, mások miért nem. Nézze meg, milyen hibákat okoznak a hibás kifejezések.

200?"200px":""+(this.scrollHeight+5)+"px");">
2 + "karakterlánc";
6 + "14";
"doboz" - "voks";
1 * "11b"
"148" * "1e6";


3. Írjunk két változót felcserélő programot! Azaz:

200?"200px":""+(this.scrollHeight+5)+"px");">
a = 6502
b=8086


Legyen a egyenlő 8086 és b egyenlő 6502. Ehhez hozzon létre egy harmadik változót, és végezzen egyszerű permutációkat. Győződjön meg arról, hogy a probléma megfelelően megoldódott: hívja a print(a,b) parancsot a csere előtt és a print(a,b) parancsot utána.

Tetszett a cikk? Oszd meg