Programavimas su Lua

Posted: 2014-11-08 in Pezalai
Žymos:,

Lua | Programavimas | Darau, blėJaučiu, kad šitas įrašas – tikrai ne populiarumo kėlimui 😀 Bet vis tiek jį parašysiu, nes, blė, norisi.

Mano, musėt, karma tokia — per savo profesionalią programuotojo karjerą beveik jokiais „meinstrymais“ ir neprogramavau. Kažkiek buvo C, kažkiek C++, kažkiek Java… Python naudojau tik savo malonumui, nors ganėtinai „naglai“. Na, prie „meinstrymų“ galima ir Oracle PL/SQL priskirti bei shell skriptų rašymą. Groovy buvau pradėjęs naudoti, bet taip ir nesusidraugavom — pritrūko laiko.

Karma tęsiasi. Dabar esu jau kiek pažengęs Lua krapštytojas. Kol kas nesutikau nė vieno, net menkai pažįstamo, programuotojo, kuris rimtai dirbtų su šia kalba. Tiesa, Lua galima iš dalies priskirti prie „meinstrymų“, bet Lietuvoje ji ganėtinai reta — kam iš kolegų (plačiąja prasme) pasakau, kad su tokia dirbu, tai visi kiek simboliškai išverčia akis ir klausia, kas tas per žvėris yr.

Ta proga aš nusprendžiau šiek tiek papildyti lietuvišką internetą keletu informacijos nuotrupų apie šią kalbą. Nemanau, aišku, kad tai labai vertinga, nes vis tiek visi programuotojai visko ieško ir šviečiasi angliškai, bet gal kam bus šiaip įdomu pasiskaityti. Pradėsiu nuo truputuko istorijos, o paskui aprašysiu įprastų ir reikalingų konstrukcijų detales.

Lua yra dinamiškai tipizuojama ir interpretuojama kalba. Kaip ir Python, taip ir Lua kodą galima sukompiliuoti į baitkodą, šitaip savo darbą kiek obfuskuojant. Dar Lua, kaip jokia kita man pažįstama kalba, dažnai naudojama intarpais su C ir C++ kodu, t.y. tokiam hibridiniam programavimui, kai kažkokias programos dalis yra lengviau ir paprasčiau suskriptinti ir įterpti į žemo lygio (sąlyginai) programą.

Lua taip pat, kaip jokia kita interpretuojama kalba, baisiai tinka visokiems mažiems įrenginiams: maršrutizatoriams, išmaniesiems komutatoriams ir kitokiai smulkiai MIPS ar ARM architektūra pagrįstai įrangai. Tai dėl to, kad Lua yra kalba „be batareikų“: jos bazinės bibliotekos yra mažutės, o virtuali mašina užima vos tris megabaitus. Ši kalba buvo viena iš pirmųjų, kuri leido maršrutizatorių web sąsajoms naudoti skriptus, o ne kompiliuojamą CGI.

Lua atsiradimo istorija irgi įdomi. Buvo kažkokie ten žiaurūs Brazilijos vyriausybės apribojimai IT sektoriuje, kurie trukdė įsigyti įvairių programavimo įrankių ir dar kažko. Smulkmenų nežinau, tik kažką girdėjau. Tai vienas brazilas programuotojas nusprendė pasidaryti interpretuojamą skriptinimo įrankį ir taip atsirado Lua (portugališkai — mėnulis).

Kaip minėjau, Lua yra kalba „be batareikų“. T.y. jos standartinės bibliotekos suteikia tik patį pagrindinį funkcionalumą. Lyginant su Python ar Java, tai — visiška priešingybė. Anų programavimo kalbų bibliotekos yra ypač pilnos ir skirtos beveik visiems gyvenimo atvejams. Užtat su Lua labai paprasta susikurti nuosavą C biblioteką ir ją „prijungti“. Dabar jau ir tų bibliotekų yra gan daug užderėję, tik susirankiot reikia ir susikompiliuot.

Lua yra keistoka, multi-paradigminė kalba. Sakykime, netgi jos pačios, kaip kalbos, struktūra yra ribota. Joje nėra tikro objektinio programavimo, nors objektus galima „pasidaryti“ naudojant ypač lanksčius asociacinius masyvus (Lua terminais — lenteles). Atitinkamai galima susikrapštyti netgi paveldimumą, nors jo irgi „nėra“. Trumpai tariant, kalba yra labai paprasta ir tuo pačiu labai labai lanksti, leidžianti visaip įvairiai išsidirbinėti.

Mano jausmai Lua labai mišrūs: nuo begalinio susižavėjimo iki noro daužyti galvą į sieną. Aišku, šito būna visų programuotojų gyvenimuose. Bet Lua tikrai yra savotiškai ypatinga. Sakykim, su Java kalbos žiniomis man prisėsti prie Python buvo vienas juokas. Daug kas iš principo panašu, tik… paprasčiau. Lua, tuo tarpu, yra retos rūšies atstovas. Kažkada domėjausi Ruby kalba, bet nė „Hello, World“ neparašiau. Ten irgi kažkas šiek tiek kitokio.

Šiandienai — keletas Lua pagrindų.

Kažkas apie kintamuosius ir truputuką sintaksę

Lua sintaksė yra „žmogiška“, t.y. ne iš C operos, kaip kad C++, Java ar C#. Joje naudojami žodelyčiai if… then, end, or, and ir panašiai. t.y. kodo blokai „apkabinami“ ne skliausteliais, o žodžiais:

x = 10
y = 5
if x > 10 then
    print("Daugiau")
elseif x == 10 and y ~= 5 then
    print("Apylygiai")
elseif x == 10 and y == 5 then
    print("Kapitaliai lygu")
else
    print("Mažiau")
end

Šitas pavyzdėlis, aišku, yra nesąmoningo algoritmo pavyzdys, bet ką jau čia. Dar atkreipkite dėmesį, kaip „nelygu“ operatorius Lua užrašomas — su tilde, o ne su šauktuku.

Kas susipažinę su Python, tie žino, kad ten egzistuoja tuplai — keletas kintamųjų, sudėti į skliaustelius. Tas labai džiugina, kai iš funkcijos norisi grąžinti kelias reikšmes. Bet visgi, tuplas — tai kelių kintamųjų vienas rinkinys. Ir jeigu bandysite priskirti mažesniam tuplui didesnį ar atvirkščiai — programa nuluš.

Tuo tarpu Lua leidžia tiesiog priskirti, grąžinti ir visaip vartalioti kintamuosius krūvomis. Bet ne tuplais. Tiesiog va taip:

x, y = 10, 5

„x“ bus 10, o „y“ — 5.

Taip, va, galima kintamuosius ir sukeisti:

x, y = y, x

Ir, be abejo, iš funkcijos grąžinti:

return x, y, z

Labai patogu. Be to, labai svarbu žinoti, Lua kalboje egzistuoja nil reikšmė. Norint deklaruoti kintamąjį galima tiesiog parašyti atskiroje eilutėje jo pavadinimą ir viskas — jis bus sukurtas su reikšme nil. Rimtas atvejis, kada verta sukurti kintamąjį be reikšmės — tai sukurti vietinį kintamąjį, pavyzdžiui, tik funkcijos erdvėje. Tam yra naudojamas kontrolinis žodelytis local:

local x

Funkcijoje sukurtas kintamasis bus prieinamas tik tai funkcijai. Modulyje local kintamasis bus prieinamas tik tam moduliui. Ir netgi cikle ar if… then bloke sukurtas vietinis kintamasis bus prieinamas tiktai tam bloke. Jei sukursite vietinį kintamąjį cikle, tai po ciklo jo jau nerasite. Šitą reikia įsiminti 🙂

Taigi, dabar atspėkite, kas čia bus:

local x, y, z = 10, 5

Ogi „x“ ir „y“ kintamieji turės reikšmes 10 ir 5, o „z“ bus nil. Bet toks kintamasis egzistuos vietinėje erdvėje.

Tiesa, jei kuriate globalų kintamąjį su reikšme nil, tai aš visgi dėl kodo skaitomumo ir grožio rekomenduočiau jį aprašyti su ta tuščia reikšme:

x = nil

Kas čia dar navarotlivesnio su tais kintamaisiais… a, Lua shell’e neveikia local. Na, jei ten tiesiog bandysite kažkokį mini kodo gabaliuką parašyti/pakopijuoti.

Labai svarbu įsiminti ir įsisąmoninti, kad Lua viskas yra true išskyrus nil ir false. Taip, jei kintamajam priskirsite skaičiuką 0, tai tas kintamasis bus true. Na, užtai patikrinti, ar koks nors objektas inicializuotas labai paprasta:

if not zia_object then
    ...
end

Ir dar baisiai smagu Lua kalboje naudoti or. Sakykim, kažkokia funkcija grąžina eilutę (string’ą). Bet ne visada. Gal kartais kažkas nulūžta ir funkcija grąžina nil arba iš viso nieko negrąžina, tai vis tiek gaunasi nil. Priskirti default reikšmę yra yzy-pyzy:

x = bad_bad_function(y) or ""

Nu ir visada būsite garantuoti, kad „x“ tikrai bus string’as. Šitas defaultinimas Lua programuotojui turi įaugti į kraują. Čia va dėl to, kas Lua viskas yra true išskyrus nil ir false

Taigi dabar trumpai apie vidinius Lua tipus. Kintamieji dinamiškai tipizuojami į tris tipus: boolean, number ir stringBoolean turi rezervuotus žodelyčius true ir false, čia nėra ir ką daug šnekėti. Number yra realieji skaičiai. Lua neturi integerių, o ir nx jie apskritai reikalingi. Tačiau specifinėms aparatūrinėms platformoms galima Lua mašinką susikompiliuoti su bet kokiais numberiais, kad ir sveikaisiais – jei to užtenka ir jei tik tam yra aparatūrinis palaikymas. O štai stringai, bestijos, jau yra ne paprasti kintamieji, o objektai su savais metodais. O jei jau prakalbom apie objektus, tai teks ir Lua lentukes paminėti… bet apie lentukes kitą kartą. Bet apie stringus reikia dar truputuką.

Lua stringai yra binariniai duomenai. Galite žiūrėti į juos panašiai, kaip į baitų masyvą. Nėra jokių ten terminuojančių simbolių ir panašiai. Viskas nuo 0 iki 255. Bet dėl šios priežasties Lua ir su unikodu nelabai draugauja.

Stringai iš dalies dinamiškai konvertuojami į kitus tipus. Sakykim:

x = "5" + 4

Rezultatas bus skaičius 9. Bet, kaip sakiau, iš dalies, nes…

Užtai Lua stringų palyginime nėra tokios nesąmonės, kaip PHP. T.y. “10” == 10 bus false. T.y. stringai į skaičiukus automatiškai šiuo atveju nesiverčia. Reikėtų bandyti tonumber(“10”) == 10, tada true būtų.

Ai, beje, bandant su nepaverčiamais stringais atlikti kokią nors matematinę operaciją iššoks error’as.

Stringai „apkabinami“ tiek viengubomis kabutėmis, tiek dvigubomis. Skirtumo nėra, yra tik estetinis pasitenkinimas. Aš viengubų kabučių, pavyzdžiui, nemėgstu, man iki šiol dvigubos reiškia eilutę, o viengubos – vieną simbolį. Bet čia tik mano asmeninis pasirinkimas.

Kaip ir daugumoj dinamiškai tipizuojamų kalbų, stringai sujungimui turi atskirą operatorių:

x = "organas" .. " raibas"

Du taškiukai sulipdo stringus. Jie sulipdo viską išskyrus boolean tipo kintamuosius ir nil. Na, ir lentukes, bet apie jas kitą kartą. Dėl to sujunginėjant neaiškios kilmės kintamuosius verta naudoti tostring():

x = "organas" .. tostring(is_raibas)

Skaičiukus galima paversti stringais ir juos sulipdant su tuščia eilute:

x = 20 .. ""
x == "20" -- TRUE!!!

Galima visokius simbolius escapinti. Na, pavyzdžiui, nauja eilutė bus tradiciškai \n.

Jeigu reikia į kodą įterpti pažodinę eilutę, t.y. sukurti stringą iš kelių eilučių, tai galima naudoti dvigubus skliaustukus:

page = [[
    <HTML>
    <HEAD>
    <TITLE>An HTML Page</TITLE>
    </HEAD>
    <BODY>
     <A HREF="http://www.lua.org">Lua</A>
     [[a text between double brackets]]
    </BODY>
    </HTML>
    ]]

Kažkas tokio. Ai, dar stringai yra nekeičiami (immutable). T.y. kiekvienas stringas yra vienintelis nepakartojamas. Jei stringą pamodifikuosite, tai sukursite naują stringą su pritaikytu pakeitimu.

O pabaigai apie Lua komentarus. Komentarai pradedami dviem minusiukais:

-- Čia yra Lua komentaras

O jei reikia išsilieti, tai tada irgi dvigubi skliaustukai naudojami:

--[[ Labai ilgas
ir, be jokio abejo,
neišpasakytai išsamus komentaras.
Neaišku net, kam tokio reikėjo
]]

Tai va. Čia toks įvadėlis. Apie smulkmenas visokias, ciklus, ir dar šį bei tą – kitukart. Juo labiau, kad aš noriu jumi tik truputuką supažindinti, o ne išmokyti. Be to, ir meškiuko efektas suveikia – jums beaiškindamas gal ir pats šį tą suprasiu.

Advertisements
Komentarai
  1. Vytas parašė:

    “elseif x == 10 and y = 5” then <– cia neturetu buti y == 5 ? 🙂

  2. Adis parašė:

    Oooo, Lua.

    Programavimo kalba, su kuria daugiausia teko dirbti.

    “PSI: Sibiro konflikte” viskas, kas buvo ne hardcodinta, buvo ant lua. Tai ir sėdėdavau, scrptindavau (nors daugiau kolegė scirptindavo), unitų characteristikas balansuodavau…

    Patiko.

  3. Alkas parašė:

    Geras. Fainas straipsnis, įdomu buvo pamatyt kas per reikalas ta Lua 🙂

  4. Dalius parašė:

    Gausiai Asterisk’ą hakiname ir ten yra galimybė rašyti dialplanus asterisk’iniu konfigu, AEL arba LUA kalba. Tai tiek asterisk’inę, tiek AEL naudoju, o LUA tik šmėžuoja. Niekaip neprisiverčiau išbandyti, nors gal perskaičius šitą straipsnį kas nors pasikeis 😀

  5. Liudas parašė:

    Butų labai faina, jeigu būtu LUA knygos išverstos lietuvių kalba. 🙂

  6. rr101ef parašė:

    Lua naudojama vienoje geriausių Machine Learning bibliotekų, Torch. Gan sudėtinga mokytis, nes pranešimai apie klaidas keistoki, o jų gūglinimas mažai ką duoda.

Parašykite komentarą

Įveskite savo duomenis žemiau arba prisijunkite per socialinį tinklą:

WordPress.com Logo

Jūs komentuojate naudodamiesi savo WordPress.com paskyra. Atsijungti / Keisti )

Twitter picture

Jūs komentuojate naudodamiesi savo Twitter paskyra. Atsijungti / Keisti )

Facebook photo

Jūs komentuojate naudodamiesi savo Facebook paskyra. Atsijungti / Keisti )

Google+ photo

Jūs komentuojate naudodamiesi savo Google+ paskyra. Atsijungti / Keisti )

Connecting to %s