Contacte

Introducere în Lua. Vrei să știi totul. Lua Language Learning lua de la zero

Un prieten apropiat de-al meu a mers recent la un interviu de angajare cu o companie locală de dezvoltare de jocuri. Nu am de gând să dau nume aici, doar să spun că a fost un fel de mare butic de dezvoltare a jocurilor în Vancouver. Nu și-a găsit un loc de muncă, dar astăzi nu vorbim despre el. Personal, cred că unul dintre motive s-a datorat lipsei lui de relații de prietenie cu limbajul de scripting pe care îl folosesc.

Introducere

Sunt în acest domeniu în timp ce predau elevilor programarea jocurilor, dar acesta este subiectul căruia nu i-am acordat suficientă atenție în trecut. Acoperim Unreal Script ca parte a cursului Utilizarea existente. Dar nu am considerat de fapt motorul de script ca parte a utilităților sau parte a motorului. Așa că, înarmat cu un site web, am decis să rup această mică barieră. Rezultatul este descris în acest document.

Singurul lucru, nu sunt sigur cât de mare va fi acest document. Îl pot descompune în mai multe părți mici sau îl pot publica în întregime într-o tiradă lungă de la început până la sfârșit. Oricum, voi decide acest lucru puțin mai târziu, când îmi voi pune notele într-un format mai semnificativ și mai consistent.

De ce și de ce nu?

În primul rând, de ce să folosiți un limbaj de scripting? Cea mai mare parte a logicii jocului poate fi scrisă într-un limbaj de scripting pentru diverse scopuri, mai degrabă decât să fie programată ca parte a motorului de joc. De exemplu, încărcarea sau inițializarea unui nivel. După încărcarea nivelului, este posibil să doriți să traduceți scena în planul de joc sau poate doriți să afișați un text preliminar. Folosind un sistem de scripting, puteți face ca anumite obiecte din joc să îndeplinească sarcini specifice. De asemenea, luați în considerare implementarea inteligenței artificiale. Personajele non-play trebuie să știe ce să facă. Programarea fiecărui NPC „manual” în corpul motorului de joc va complica inutil sarcina. Când doriți să schimbați comportamentul unui NPC, va trebui să vă recompilați proiectul. Cu un sistem de scripting, puteți face acest lucru în mod interactiv, schimbând comportamentul și salvând setările.

Am atins puțin despre această problemă în ultimul paragraf, despre asta vom vorbi puțin mai târziu. Întrebarea este, de ce să nu scrieți logica exclusiv în C/C++? Mai simplu spus, că pe termen lung programatorul are faptul că totul cade direct asupra lui și pleacă, respectiv, de la codul jocului, în același timp va trebui să scrie un motor și utilități etc. Dar acum putem transfera unele dintre sarcinile de funcționalitate către designerii de nivel cu un limbaj de scripting simplu. Ei pot începe să modifice nivelul și să optimizeze jocul. Iată un exemplu:

Să ne imaginăm că Joe, programatorul nostru nefericit, scrie el însuși întregul motor al jocului, instrumentele și logica jocului. Da, Joe va avea probleme, dar să presupunem că nu-i pasă. Îl avem și pe Brandon, designerul jocului. Brandon este un copil destul de inteligent cu idei grozave pentru joc. Și astfel, codificatorul nostru Joe se târăște și implementează toată logica jocului folosind setul de instrumente pe care l-a dezvoltat pe baza proiectului inițial al lui Brandon. Totul este bine la birou. Prima fază s-a încheiat, iar Joe și Brandon stau în sala de consiliu și își revizuiesc munca considerabilă. Brandon observă câteva probleme cu jocul, care nu se comportă corect. Așa că Joe se întoarce la cod și face modificările necesare. Acest proces poate dura o zi, cel puțin dacă nu este o schimbare banală. Apoi încă o zi pentru a recompila proiectul. Pentru a nu pierde nicio zi în plus, majoritatea birourilor părăsesc procesul de asamblare peste noapte. Deci, după cum putem vedea, durează 24 de ore până când Brandon va vedea schimbarea pe care a cerut-o.

Acum, să presupunem că protagonistul nostru Joe decide că implementarea logicii jocului folosește motorul de script în avantajul său. Va dura ceva timp la început, dar simte că va beneficia pe termen lung. Și astfel, schimbă unele funcționalități de la motorul jocului la sistemul de script al jocului. De asemenea, scrie toată logica jocului în sistemul de scripting menționat anterior. Și așa, când îl întâlnește pe Brandon și designerul observă ceva care nu corespunde ideii sale, Joe deschide rapid consola, face câteva modificări în scenariu, repornește jocul și vede deja noul comportament. Modificările pot fi făcute imediat și afișate imediat, în loc să aștepte recompilarea. Și dacă Joe era deosebit de expresiv, sistemul de scripting ar putea fi folosit pentru utilități și disponibil pentru proiectanții de niveluri atunci când construiesc niveluri. Dacă urmați această cale, atunci cu puțină pregătire, designerii de nivel ar putea seta ei înșiși evenimente de joc, cum ar fi declanșatoare, uși, alte evenimente de joc și să se bucure de viață fără a solicita programatorul.

Acesta este un exemplu destul de artificial și poate fi puțin exagerat, dar sper că arată diferența dintre abordări. Deci, ce încercăm să facem cu acest model, ceea ce înseamnă să trecem la date mai gestionate automat. Deci, în esență, unde mergem:

  1. Codificatorul este interesat să scrie codul motorului/uneltelor, nu logica jocului.
  2. Timpul a fost petrecut scriind motorul de joc / instrumentele.
  3. Designerilor le place să se joace cu lucrurile. Scriptarea le oferă libertatea de a proiecta niveluri și funcționalități. De asemenea, le oferă mai multă flexibilitate pentru a experimenta lucruri pentru care ar implica în mod normal un programator.
  4. Nu trebuie să recompilați dacă doriți să schimbați funcționalitatea jocului. Schimbați doar scenariul.
  5. Vrei să rupi legătura dintre mașină și codul jocului. Ar trebui să fie în două părți separate. În acest fel va fi convenabil să folosiți motorul pentru viitoarele sequele (sper).

Voi face niște predicții aici. În următorii 5 ani, designerii de niveluri vor trebui să facă mai mult decât să construiască niveluri. Ei trebuie să poată folosi scripturi pentru scenele jocului. Mai multe companii de ultimă oră au adoptat deja această abordare. De asemenea, puteți vedea această metodă de integrare în editori precum UnrealEd și Aurora toolset Bioware.

Clarificare și dezgustător

Sper că acum ați acceptat deja cuvintele mele și ați dorit să includeți o componentă de script în jocul dvs. Deci următoarea întrebare este: cum naiba faci asta?

Ceea ce voi folosi pentru componenta mea de script este un motor de script injectabil Lua... La început, voi spune că nu sunt un expert în Lua, dar este un limbaj relativ simplu și nu necesită o învățare obositoare pentru a-l stăpâni. Unele dintre exemplele pe care le voi trece mai târziu sunt destul de simple. La sfârșitul acestui document, voi include câteva materiale de referință suplimentare. Pentru a fi corect, există și alte limbaje de scripting precum Small, Simkin, Python, Perl. Cu toate acestea, Lua este un limbaj frumos și curat. Acesta este un avantaj foarte bun.

Lua este open source. Acest lucru este bun pentru că: (a) obțineți sursa pentru limba și puteți săpa cât doriți, (b) este gratuit. Îl poți folosi în aplicații comerciale fără a arunca bani. Ei bine, pentru proiecte non-comerciale înțelegi tu însuți gratis == bine.

Deci cine folosește Lua în prezent? Lua este scris de un birou sharashka și este folosit doar de săraci? Mmm... nu chiar. Lua nu a apărut ieri și a fost folosită de personalități cunoscute:

  • Lucasarts
    • Grim fandango
    • Evadare de pe Insula Maimuțelor
  • Produse biologice
    • Nopți de iarnă

Ok, destul cu cine-este-cine dintre dezvoltatorii lua. Puteți vedea asta singur pe site-ul lua.

Să începem cu adevărat simplu. Primul lucru pe care trebuie să-l construim ne va arăta cum este folosit interpretul lua. Ce este necesar pentru aceasta:

  1. Obținerea codului interpretului Lua.
  2. Configurarea mediului de dezvoltare.
  3. Construirea interpretului de la zero.

Hei, am crezut că ai spus destule deversări?

E suficient? Deci, să trecem la treabă. Puteți obține tot codul sursă Lua de pe site-ul oficial. De asemenea, aș dori să iau o secundă și să subliniez că există o nouă versiune a lua 5.0 la orizont. Nu voi discuta despre această versiune în acest articol. Mă voi ocupa mai târziu, dar deocamdată vom folosi 4.0.1.

Primul lucru pe care îl vom face este să construim biblioteca lua. Astfel, nu este nevoie să includem sursele de fiecare dată când construim proiectul. Nu este dificil și nu acesta este scopul lecțiilor noastre. Prin urmare, am inclus biblioteca în avans ca parte a acestui articol. Am folosit o bibliotecă statică pentru acest exemplu. Da, poate l-aș fi construit ca DLL, dar pentru un sistem de scripting, o bibliotecă statică este puțin mai rapidă. Observați, nu mult, dar mai repede.

Invitatul nostru de astăzi este un adevărat luptător al frontului ascuns. Poate că l-ați văzut în jocuri (World of Warcraft, Angry Birds, X-Plane, S.T.A.L.K.E.R.) sau produse Adobe (Lightroom), dar nici măcar nu v-ați gândit la existența lui. Între timp, această limbă are deja aproape 25 de ani și, în tot acest timp, ne-a făcut imperceptibil viața virtuală puțin mai bună.

Referință rapidă

Lua ar fi fost inventată în 1993 de Universitatea Catolică din Rio de Janeiro. Numele este tradus din portugheză cu Luna, iar creatorii cer în mod convingător să nu scrie LUA, pentru ca, Doamne ferește, cineva să nu ia numele drept abreviere. Este un limbaj de scripting multi-paradigmă care utilizează modelul prototip OOP.

Tastarea este dinamică aici, iar metatablele sunt folosite pentru a implementa moștenirea, adică este un instrument excelent pentru extinderea capabilităților produsului dvs. Mai mult, datorită compactității sale, este potrivit pentru utilizare pe aproape orice platformă. Judecă-te singur: tarball Lua 5.3.4 cântărește doar 296 kiloocteți (necomprimat - 1,1 megaocteți), interpretul (scris în C) pentru Linux - de la 182 la 246 kiloocteți, iar setul standard de biblioteci - încă 421 kiloocteți.

Codul

Ca aspect și capabilități, Lua arată ca o altă încercare de a reface JavaScript, dacă nu pentru faptul că acesta din urmă a apărut doi ani mai târziu. Convinge-te singur:

Să începem cu cea tradițională:

imprimare („Bună lume”)

De acord, familiar și nu foarte informativ. Un exemplu mai interesant din punctul de vedere al familiarității cu Lua este calculul factorialului unui număr introdus:

Fapt funcțional (n)
dacă n == 0 atunci
întoarce 1
altfel
returnează n * fapt (n-1)
Sfârșit
Sfârșit

Imprimați ("introduceți un număr:")
a = io.read ("* număr") - citește un număr
imprimare (fapt (a))

Totul este foarte clar. Apropo, Lua acceptă atribuirea paralelă:

Și, în sfârșit, un exemplu destul de simplu folosind biblioteci:

#include
#include
#include
#include
#include

Int main (void) (
char buff;
int eroare;
lua_State * L = lua_open (); / * deschide Lua * /
luaopen_base (L); / * deschide biblioteca de bază * /
luaopen_table (L); / * deschide biblioteca de tabel * /
luaopen_io (L); / * deschide biblioteca I / O * /
luaopen_string (L); / * deschide șirul lib. * /
luaopen_math (L); / * deschide lib. matematică. * /

While (fgets (buff, sizeof (buff), stdin)! = NULL) (
eroare = luaL_loadbuffer (L, buff, strlen (buff), "line") ||
lua_pcall (L, 0, 0, 0);
dacă (eroare) (
fprintf (stderr, "% s", lua_tostring (L, -1));
lua_pop (L, 1); / * mesaj de eroare pop din stivă * /
}
}

Lua_close (L);
returnează 0;
}

Avantaje și dezavantaje

Deci, ce este bun la Lua?

În primul rând, după cum sa menționat deja, prin compactitatea sa și împreună cu faptul că codul sursă este scris în C, obțineți interacțiune completă cu una dintre cele mai populare limbi de pe planetă și o gamă largă de platforme disponibile.

Medii de dezvoltare

LDT (Lua Development Tools) pentru Eclipse - o extensie pentru unul dintre cele mai populare IDE-uri;

ZeroBrane Studio este un mediu specializat scris în Lua;

Decoda nu este cel mai popular IDE multiplatformă, dar va funcționa ca alternativă;

SciTE este un editor bun cu suport complet Lua;

WoWUIDesigner - ghiciți ce joc ajută acest mediu la procesarea scripturilor, inclusiv Lua?

Link-uri utile

http://www.lua.org/home.html - site-ul oficial cu toate informațiile necesare, tutorial, cărți, documentație și chiar ceva umor specific;

http://tylerneylon.com/a/learn-lua/ este un tutorial grozav de la Tyler Neylon. Potrivit pentru programatorii experimentați care cunosc bine engleza (cu toate acestea, nici cu dicționarul nu vor fi probleme mari) și care doresc doar să-și lărgească orizonturile;

https://zserge.wordpress.com/2012/02/23/lua- for-60-minutes/ - Noțiuni de bază Lua în 60 de minute de la un programator care în mod clar nu este indiferent față de acest limbaj. In rusa;

http://lua-users.org/wiki/LuaTutorial - tutorial wiki

https://youtube.com/watch?v=yI41OL0-DWM- tutoriale video pe YouTube care vă vor ajuta să înțelegeți vizual configurarea IDE și principiile de bază ale limbajului.

scripturi Lua

Un script scris în Lua nu are nicio funcție specială de la care să-și înceapă execuția. Un script poate fi gândit pur și simplu ca un set de comenzi (instrucțiuni) care sunt executate începând de la prima instrucțiune.

Un script poate fi fie foarte simplu, constând dintr-o singură comandă, fie foarte complex, care conține zeci, sute sau chiar mii de instrucțiuni. Instrucțiunile consecutive pot fi separate prin punct și virgulă (;). Cu toate acestea, această cerință este opțională, așa că tot codul de mai jos este corect din punct de vedere sintactic:

Lucrul cu variabile în Lua

Variabilele sunt folosite pentru a stoca valori în timpul execuției scriptului.

Nume variabile în Lua

Numele (identificatorii) variabilelor în Lua pot fi orice succesiune de litere, numere și litere de subliniere care nu încep cu un număr.

Notă

Lua este sensibil la majuscule, așa că abc, Abc, ABC sunt nume diferite.

Tabelul de mai jos arată cuvintele care sunt rezervate de limba Lua și nu pot fi folosite în nume de variabile:

și break do elseif

final false pentru funcția dacă

în local nil nu sau

repetă return apoi adevărat până când

În plus, toate numele care încep cu un caracter de subliniere urmat de majuscule (de exemplu, _VERSION) sunt de asemenea rezervate.

Ce variabile există în Lua?

Variabilele în Lua pot fi globale sau locale. Dacă o variabilă nu este declarată în mod explicit ca locală, este considerată globală.

Lua variabile globale

Variabila globală apare atunci când i se atribuie prima valoare. Înainte ca prima valoare să fie atribuită, apelul la variabila globală produce zero.

MsgBox (tostring (g)) -> nil

MsgBox (tostring (g)) -> 1

O variabilă globală există atâta timp cât există mediul de execuție a scriptului și este disponibilă pentru orice cod Lua care rulează în acel mediu.

Dacă este necesar, puteți șterge în mod explicit o variabilă globală prin simpla atribuire a unei valori zero.

g = 1 - creați o variabilă globală g cu valoarea 1

g = nil - ștergeți variabila globală g

MsgBox (tostring (g)) -> nil

Toate variabilele globale sunt câmpuri ale unui tabel obișnuit numit mediu global. Acest tabel este accesibil prin variabila globală _G. Deoarece câmpurile mediului global sunt toate variabile globale (inclusiv _G însuși), atunci _G._G == _G.

Lua variabile locale

Orice variabilă locală trebuie declarată explicit folosind cuvântul cheie local. Puteți declara o variabilă locală oriunde în script. Declarația poate include atribuirea unei valori inițiale variabilei. Dacă nu este atribuită nicio valoare, variabila conține zero.

local a - declara o variabilă locală a

local b = 1 - declarați o variabilă locală b, atribuiți-i valoarea 1

local c, d = 2, 3 - declarați variabilele locale c și d, atribuiți-le valorile 2 și 3

Sfera de aplicare a unei variabile locale începe după declarație și continuă până la sfârșitul blocului.

Notă

Sfera de aplicare a unei variabile este o bucată de cod de program în cadrul căreia puteți accesa valoarea stocată într-o anumită variabilă.

Un bloc înseamnă:

corpul structurii de control (dacă-atunci, altfel, pentru, în timp ce, repetă);

corp funcțional;

o bucată de cod inclusă în cuvintele cheie do ... sfârșește.

Dacă o variabilă locală este definită în afara oricărui bloc, domeniul ei se extinde până la sfârșitul scriptului.

local i = 1 - variabila i este locală în cadrul scriptului

in timp ce eu<= a do - цикл от 1 до 5

local a = i ^ 2 - variabila a este locală în bucla while

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

MsgBox (a) ->

dacă i> 5 atunci

local a - variabila a este locală în interiorul atunci

MsgBox (a) -> 10

MsgBox (a) -> 5 (aici referire la global a)

local a = 20 - variabila a este locală în interiorul do-end

MsgBox (a) -> 20

MsgBox (a) -> 5 (aici referire la global a)

Notă

Ori de câte ori este posibil, se recomandă utilizarea variabilelor locale în locul celor globale. Acest lucru va evita „aglomerarea” spațiului de nume global și va oferi performanțe mai bune (deoarece accesarea variabilelor locale în Lua este oarecum mai rapidă decât la global).

Tipuri de date Lua

Ce tipuri de date acceptă Lua?

Lua acceptă următoarele tipuri de date:

1. Nil (nimic). Corespunde faptului că o variabilă nu are valoare. Acest tip este reprezentat de o singură valoare, zero.

2. Boolean (logic). Acest tip include valorile false și adevărate.

Când se efectuează operații logice, nul este considerat fals. Toate celelalte valori, inclusiv numărul 0 și șirul gol, sunt considerate adevărate.

3. Număr (numeric). Servește pentru a reprezenta valori numerice.

Constantele numerice pot conține o parte fracțională opțională și o ordine zecimală opțională, specificate prin caracterele „e” sau „E”. Constantele numerice întregi pot fi specificate în hexazecimal folosind prefixul 0x.

Exemple de constante numerice valide: 3, 3.0, 3.1415926, 314.16e-2, 0xff.

4. șir (șir). Servește pentru a reprezenta șiruri.

Valorile șirurilor sunt specificate ca o secvență de caractere, cuprinse între ghilimele simple sau duble:

a = „acesta este un șir”

b = „aceasta este a doua linie”

Șirurile cuprinse între ghilimele duble pot interpreta secvențe de escape asemănătoare C (secvențe de escape) care încep cu caracterul „\” (bară oblică inversă):

\ b (spațiu),

\ n (avans de linie),

\ r (întoarcerea căruciorului);

\ t (filă orizontală),

\\ (bară oblică inversă);

\ "" (citat dublu);

\ "(ghilimele unice).

Notă

Un caracter dintr-un șir poate fi reprezentat și prin propriul cod folosind o secvență de escape:

unde ddd este o succesiune de cel mult trei cifre.

Pe lângă ghilimele, pot fi folosite și paranteze pătrate duble pentru a defini un șir:

Definirea unui șir cu paranteze pătrate duble permite ignorarea tuturor secvențelor de evacuare, adică șirul este creat exact așa cum este descris:

local a = [] în Lua] =]

Va exista un termen: „definiția șirului [] în Lua”

5. Funcție. Funcțiile din Lua pot fi scrise în variabile, transmise ca parametri altor funcții și returnate ca rezultat al executării funcțiilor.

6. Tabelul. Un tabel este un set de perechi cheie-valoare, care sunt numite câmpuri sau elemente de tabel. Atât cheile, cât și valorile câmpurilor din tabel pot fi de orice tip, cu excepția zero. Tabelele nu au o dimensiune fixă: le puteți adăuga oricând un număr arbitrar de elemente.

Mai multe detalii - în articolul „Crearea tabelelor în Lua”

7. Date utilizator (date utilizator). Este un tip de date special. Valorile de acest tip nu pot fi create sau modificate direct într-un script Lua.

Datele utilizator sunt folosite pentru a reprezenta tipuri noi create în programul de apelare script sau în bibliotecile scrise în C. De exemplu, bibliotecile de extensie Lua pentru „CronosPRO” folosesc acest tip pentru a reprezenta obiecte precum:

bănci de date (clasa Bank);

baze de date (clasa de bază);

înregistrări (clasa Record), etc.

8. Fir (fir). Corespunde fluxului de executie. Aceste fluxuri nu sunt conectate în niciun fel cu sistemul de operare și sunt acceptate exclusiv prin intermediul Lua în sine.

Cum se setează tipul unei variabile în Lua?

Lua nu stabilește în mod explicit tipul unei variabile. Tipul unei variabile este setat în momentul în care o valoare este atribuită variabilei. Orice variabilă i se poate atribui o valoare de orice tip (indiferent de tipul de valoare pe care o conținea anterior).

a = 123 - variabila a este de tip număr

a = "123" - acum variabila a este de tip șir

a = adevărat - acum variabila a este de tip boolean

a = () - acum variabila a este de tip tabel

Notă

Variabilele de tip tabel, funcție, fir și userdata nu conțin datele în sine, ci stochează referințe la obiectele corespunzătoare. La atribuirea, trecerea la o funcție ca argument și revenirea de la o funcție ca rezultat, obiectele nu sunt copiate, sunt copiate doar referințele la acestea.

a = () - creați un tabel. O referință la tabel este plasată în variabila a

b = a - variabila b se referă la același tabel cu a

a = 10 - elementului tabelului cu indicele 1 i se atribuie valoarea 10

MsgBox (b) -> „10”

MsgBox (a) -> „20”

Restul datelor sunt valori imediate.

MsgBox (a) -> „20”

MsgBox (b) -> „10”

Cum să obțineți tipul unei variabile în Lua?

Tipul valorii stocate într-o variabilă poate fi găsit folosind tipul de funcție standard. Această funcție returnează un șir care conține numele tipului ("nil", "number", "string", "boolean", "table", "function", "thread", "userdata").

t = tip („acesta este un șir”) - t este egal cu „șir”

t = tip (123) - t este egal cu „număr”

t = tip (tip) - t este „funcție”

t = tip (adevărat) - t este „boolean”

t = tip (nul) - t este „nul”

t = tip (CroApp.GetBank ()) - t este egal cu „date utilizator”

Cum se transformă tipul unei variabile în Lua?

Lua convertește automat numerele în șiruri și invers, după cum este necesar. De exemplu, dacă o valoare șir este un operand într-o operație aritmetică, aceasta este convertită într-un număr. De asemenea, o valoare numerică care apare acolo unde este așteptat un șir va fi convertită într-un șir.

a = "10" + 2 - a este egal cu 12

a = "10" + 2 - a este egal cu "10 + 2"

a = „-5,3e-10” * „2” - a este egal cu -1,06e-09

a = „șir” + 2 - Eroare! Nu se poate converti „șir” în număr

Orice valoare poate fi convertită în mod explicit într-un șir folosind funcția standard tostring.

a = tostring (10) - a este egal cu „10”

a = tostring (adevărat) - a este egal cu „adevărat”

a = tostring (nul) - a este egal cu „nul”

a = tostring ((= „acesta este câmpul 1”)) - a este egal cu „tabel: 06DB1058”

Din exemplul anterior, puteți vedea că conținutul tabelelor nu este convertit de funcția tostring. Această transformare se poate face folosind funcția de randare.

a = randare (10) - a este egal cu „10”

a = randament (adevărat) - a este egal cu „adevărat”

a = randament (nul) - a este egal cu „nul”

a = randare ((= „acesta este câmpul 1”)) - a este egal cu „(=" acesta este câmpul 1 „)”

Puteți utiliza funcția standard tonumber pentru a converti în mod explicit o valoare într-un număr. Dacă valoarea este un șir care poate fi convertit într-un număr (sau este deja un număr), funcția returnează rezultatul conversiei, în caz contrar, returnează zero.

a = tonumber ("10") - a este egal cu "10"

a = tonumber ("10" .. ". 5") - a este egal cu 10,5

a = tonumber (adevărat) - a este „nul”

a = tonumber (nul) - a este „nul”

Aranjarea comentariilor în Lua

Un comentariu în Lua începe cu două semne minus (-) și continuă până la sfârșitul rândului.

local a = 1 - comentariu pe o singură linie

Dacă două paranteze pătrate deschise ([[)] urmează imediat caracterele „-”, comentariul este pe mai multe linii și continuă până la două paranteze pătrate de închidere (]]).

local a = 1 - [[multilinie

un comentariu ]]

Parantezele duble din comentarii pot fi imbricate. Pentru a nu le confunda, între paranteze se introduce un semn egal (=):

local a = [[Compania Kronos]] - [= [

local a = [[Compania Kronos]]

Numărul de simboluri „=" determină imbricarea:

local a = [= [definiția unui șir [] în limba Lua] =] - [== [

local a = [= [definiția unui șir [] în limba Lua] =]

Operațiuni Lua

Următoarele tipuri de operații pot fi utilizate în expresiile scrise în Lua:

1. Operații aritmetice.

Lua acceptă următoarele operații aritmetice:

+ (adăugare);

- (scădere);

* (înmulțire);

/ (Divizia);

^ (exponentiație);

% (restul diviziunii).

Notă

Operațiile aritmetice se aplică atât numerelor, cât și șirurilor de caractere, care în acest caz sunt convertite în numere.

2. Operatii de comparatie.

Următoarele operațiuni de comparare sunt permise în Lua:

== (egal);

~ = (nu este egal);

< (меньше);

> (mai mult);

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

> = (mai mare sau egal).

Notă

Operațiile de comparare returnează întotdeauna valoarea booleană adevărată sau falsă.

Regulile de conversie a numerelor în șiruri de caractere (și invers) nu funcționează pentru comparații, adică expresia „0” == 0 are ca rezultat fals.

3. Operații logice.

Operațiile logice includ:

și (ȘI logic).

Operatorul și returnează primul său operand dacă este fals sau nul. În caz contrar, operația returnează al doilea operand (mai mult, acest operand poate fi de orice tip).

a = (nul și 5) - a este zero

a == (fals și 5) - a este egal cu fals

a == (4 și 5) - a este egal cu 5

sau (SAU logic).

Operatorul sau returnează primul operand dacă nu este fals sau nul, în caz contrar returnează al doilea operand.

a == (4 sau 5) - a este egal cu 4

a == (fals sau 5) - a este egal cu 5

Notă

Operațiile booleene și și sau pot returna valori de orice tip.

Operatorii logici și și sau evaluează valoarea celui de-al doilea operand numai dacă trebuie returnat. Dacă nu este necesar, al doilea operand nu este evaluat. De exemplu:

a == (4 sau f ()) - funcția f () nu va fi apelată

nu (NU logic).

Operația not returnează întotdeauna adevărat sau fals.

4. Operația de concatenare.

Pentru a concatena (uni) șiruri, utilizați operația ... (două puncte).

a = "Kronos" .. "-" .. "Inform" - variabila a va primi valoarea "Kronos-Inform"

Notă

Dacă unul sau ambii operanzi sunt numere, ei sunt convertiți în șiruri.

a = 0..1 - variabila a va primi valoarea „01”

5. Operatia de obtinere a lungimii.

Lua definește un operator de lungime # care poate fi folosit pentru a obține lungimea unui șir.

a = "șir"

len = #a - len este 6

len = # „o altă linie” - len este 10

Notă

De asemenea, puteți utiliza operația # pentru a afla indexul (sau dimensiunea) maximă a unui tablou. Mai multe detalii - în articolul „Lucrul cu matrice în Lua”.

Prioritatea operațiunii în Lua

În Lua, operațiunile sunt efectuate în funcție de următoarea prioritate (în ordine descrescătoare):

2.nu # - (unară)

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

Apelarea scripturilor din formulare

Fiecare formular (inclusiv formularele imbricate) are asociat un script separat, care de obicei conține funcții care gestionează evenimentele formularului și elementele sale.

Când formularul este lansat, scriptul său este încărcat în mediul global. Când are loc un eveniment al unui formular sau al elementului său, sistemul apelează funcția de gestionare asociată cu acest eveniment.

Trebuie remarcat faptul că scriptul de formular, deși nu conține un apel la funcția modul, este de fapt un modul. Aceasta înseamnă că variabilele declarate în scriptul formular fără cuvântul cheie local nu sunt mutate în mediul global și sunt disponibile numai în acest script. Dacă trebuie să faceți o valoare disponibilă pentru scripturile de alte forme, aceasta trebuie să fie definită în mod explicit în tabelul global _G:

local a = _G.var

Blocuri de instrucțiuni

Principalii operatori Lua sunt:

misiune;

operator condițional;

operatori de organizare a buclelor.

Un grup de instrucțiuni poate fi combinat într-un bloc (instrucțiune compusă) folosind construcția do... end.

do - începutul blocului

<оператор1>- corp bloc

<оператор2>

<операторN>

sfârşitul - capătul blocului

Blocul deschide un nou domeniu în care puteți defini variabile locale.

a = 5 - variabilă globală a

local a = 20 - în interiorul variabilei locale do-end a este definită

MsgBox (a) -> 20

MsgBox (a) -> 5 (aici apelul este deja către global a)

Operator de atribuire Lua

O atribuire modifică valoarea unei variabile sau a unui câmp de tabel. În forma sa cea mai simplă, o sarcină ar putea arăta astfel:

a = 1 - variabilei a i se atribuie valoarea 1

a = b + c - variabilei a i se atribuie suma valorilor variabilelor b și c

a = f (x) - variabilei a i se atribuie valoarea returnată de funcția f (x)

Lua permite așa-numita atribuire multiplă, atunci când mai multe variabile din stânga operatorului de atribuire primesc valorile mai multor expresii scrise în dreapta operatorului de atribuire:

a, b = 1,5 * c - a este egal cu 1; b este egal cu 5 * c

Dacă există mai multe variabile decât valori, nul este atribuit variabilelor „extra”.

a, b, c = 1, 2 - a este 1; b este 2; c este zero

Dacă există mai multe valori decât variabile, valorile „extra” sunt ignorate.

a, b = 1, 2, 3 - a este 1; b este 2; valoarea 3 nu este folosită

Atribuirea multiplă poate fi utilizată pentru a schimba valori între variabile:

a = 10; b = 20 - a este 10, b este 20

a, b = b, a - acum a este 20, b este 10

Declarație condiționată (dacă) în Lua

Declarația if testează dacă condiția specificată este adevărată. Dacă condiția este adevărată, partea de cod care urmează cuvântului cheie then (apoi secțiunea) este executată. În caz contrar, se execută codul care urmează cuvântului cheie else (secțiunea else).

dacă a> b atunci

returnează a - dacă a este mai mare decât b, returnează a

returnează b - în caz contrar, returnează b

Secțiunea Else este opțională.

în cazul în care un< 0 then

a = 0 - dacă a este mai mic decât 0, setați a la 0

În loc de instrucțiuni if ​​imbricate, puteți utiliza constructul elseif. De exemplu, următorul cod:

va fi mai ușor de înțeles dacă îl înlocuiți cu următoarele:

returnează „Ivan” - dacă a este 1

elseif a == 2 atunci

returnează „Petru” - dacă a este 2

elseif a == 3 atunci

returnează „Sergey” - dacă a este 3

returnează „Nu există un astfel de jucător” - dacă a nu este niciunul dintre cele de mai sus

Lua buclă while

Instrucțiunea while este concepută pentru a organiza bucle cu o precondiție și are următoarea formă:

in timp ce do

... - corpul ciclului

Înainte de fiecare iterație a buclei, condiția este verificată :

dacă condiția este falsă, bucla se termină și controlul este transferat la prima instrucțiune care urmează instrucțiunii while;

dacă condiția este adevărată, corpul buclei este executat, după care se repetă toate acțiunile.

în timp ce i> 0 do - buclă de la 10 la 1

t [i] = „câmp” ..i

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

în timp ce i> 0 do - în căutarea unei valori negative în matrice

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

i = i - 1 - altfel treceți la următorul element

dacă i> 0 atunci

MsgBox ("Indexul valorii negative:" ..i)

MsgBox („Matricea nu conține valori negative”)

Notă

Buclă cu postcondiție (repetare) în Lua

Instrucțiunea de repetiție este concepută pentru a organiza bucle cu o postcondiție și are următoarea formă:

... - corpul ciclului

pana cand

Corpul buclei este executat atâta timp cât condiția nu va deveni adevărat. Condiția este verificată după ce corpul buclei este executat, prin urmare, în orice caz, corpul buclei va fi executat cel puțin o dată.

Însumați valorile matricei a până când suma depășește 10

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

suma = suma + a [i]

până la suma > 10

MsgBox („Stivuite” ..i .. „articole. Suma este” ..sumă)

Puteți utiliza instrucțiunea break pentru a ieși din buclă înainte ca aceasta să se încheie.

Notă

Mai multe detalii despre caracteristicile utilizării operatorului break - în articolul „Instrucțiunile break și return”

Lua pentru bucle

Declarația for este concepută pentru a organiza bucle și poate fi scrisă în două forme:

simplu (numeric pentru);

extins (universal pentru).

Forma simplă a declarației for

Forma simplă a declarației for arată astfel:

pentru var = exp1, exp2, exp3 do

... - corpul ciclului

Corpul buclei este executat pentru fiecare valoare a variabilei buclei (contor) var din intervalul de la exp1 la exp2, cu pasul exp3.

Notă

Este posibil ca pasul să nu fie setat. În acest caz, se ia egal cu 1.

pentru i = 1, 10 do - bucla de la 1 la 10 cu pasul 1

MsgBox ("i este egal cu" ..i)

pentru i = 10, 1, -1 do - bucla de la 10 la 1 cu un pas de -1

MsgBox ("i este egal cu" ..i)

Notă

Expresiile exp1, exp2 și exp3 sunt evaluate o singură dată, înainte de începerea buclei. Deci, în exemplul de mai jos, funcția f (x) va fi apelată pentru a calcula limita superioară a buclei o singură dată:

pentru i = 1, f (x) do - buclă de la 1 la valoarea returnată de funcția f ()

MsgBox ("i este egal cu" ..i)

Variabila buclă este locală pentru instrucțiunea buclă și este nedefinită la sfârșitul acesteia.

pentru i = 1, 10 do - bucla de la 1 la valoarea returnată de f ()

MsgBox ("i este egal cu" ..i)

MsgBox ("După ieșirea din buclă, i este egal cu" ..i) - Greșit! eu sunt nul

Notă

Valoarea unei variabile de buclă nu poate fi modificată în interiorul unei bucle: consecințele unei astfel de modificări sunt imprevizibile.

Pentru a ieși din buclă înainte de a se termina, utilizați instrucțiunea break.

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

pentru i = 1, # a do - căutați o valoare negativă în tablou

dacă un [i]< 0 then - если найдено...

index = i - stochează indexul valorii găsite...

rupe - și rupe bucla

MsgBox ("Indexul valorii negative:" ..index)

Notă

Mai multe detalii despre caracteristicile utilizării operatorului break - în articolul „Instrucțiunile break și return”)

Sunt un programator sentimental. Uneori mă îndrăgostesc de limbaje de programare și apoi pot vorbi despre ele ore întregi. Vă voi împărtăși una dintre aceste ore.

Lua? Ce este asta?

Lua este un limbaj simplu încorporabil (poate fi integrat cu programele dumneavoastră scrise în alte limbi), ușor și simplu, cu un singur tip de date, cu o sintaxă uniformă. Limba perfectă de învățat.

Pentru ce?

Lua ți-ar putea fi de folos:

* dacă sunteți un jucător (pluginuri pentru World of Warcraft și multe alte jocuri)
* dacă scrieți jocuri (foarte des în jocuri, motorul este scris în C / C ++ și AI - în Lua)
* dacă sunteți programator de sistem (puteți scrie pluginuri pentru nmap, wireshark, nginx și alte utilitare în Lua)
* dacă sunteți un dezvoltator încorporat (Lua este foarte rapid, compact și necesită foarte puține resurse)

1. Învață să programezi. Macar putin. Nu contează ce limbă.
2. Instalați Lua. Pentru a face acest lucru, fie descărcați versiunea 5.2 de aici (http://www.lua.org/download.html), fie căutați-o în depozite. Versiunea 5.1 va funcționa și ea, dar rețineți că este foarte veche.

Rulați toate exemplele din articol în terminal cu o comandă de genul „lua file.lua”.

Prima impresie

Lua este un limbaj tatat dinamic (variabilele primesc tipuri „din zbor” în funcție de valorile atribuite). Poți scrie în el atât în ​​stil imperativ, cât și orientat pe obiecte sau funcțional (chiar dacă nu știi cum este, e în regulă, continuă să citești). Iată Hello world în Lua:

Prima mea aplicație lua: hello.lua print „hello world”; print ("la revedere lume")

Ce se poate spune deja despre limbă:

* comentariile pe o singură linie încep cu două cratime „-”
* parantezele și punctele și virgulă pot fi omise

Operatori lingvistici

Setul de condiționale și bucle este destul de tipic:

Instrucțiuni condiționale (nu pot exista ramuri else) if a == 0 then print ("a este zero") else print ("a nu este zero") end - formă prescurtată if / elseif / end (în loc de comutare / caz) if a == 0 then print ("zero") elseif a == 1 apoi print ("unu") elseif a == 2 apoi print ("doua") else print ("altul") end - bucla de contor pentru i = 1, 10 imprimă (i) final - buclă cu precondiția b = 5 în timp ce b> 0 face b = b - 1 final - buclă cu postcondiție repetă b = b + 1 până la b> = 5

Gândiți-vă: ce ar putea însemna bucla „for i = 1, 10, 2 do ... end”?

În expresii, puteți folosi următorii operatori pe variabile:

* atribuire: x = 0
* aritmetică: +, -, *, /,% (restul diviziunii), ^ (exponentiație)
* boolean: și, sau, nu
* comparație:>,<, ==, <=, >=, ~ = (nu-egal, da-da, în loc de obișnuitul „! =")
* concatenare de șiruri (operator „..”), de exemplu: s1 = „bună ziua”; s2 = „lume”; s3 = s1..s2
* lungime / dimensiune (operator #): s = "bună ziua"; a = #s („a” va fi 5).
* obținerea unui element prin index, de exemplu: s

Multă vreme nu au existat operații pe biți în limbaj, dar în versiunea 5.2 a apărut biblioteca bit32, care le implementează (ca funcții, nu ca operatori).

Tipuri de date

Te-am mințit când am spus că limba are un singur tip de date. Are multe dintre ele (ca orice limbaj serios):

* zero (nimic)
* numere booleene (adevărat/fals)
* numere (numere) - fără împărțire cu numere întregi / reale. Doar numere.
* șiruri - apropo, sunt foarte asemănătoare cu șirurile în pascal
* funcții - da, o variabilă poate fi de tip „funcție”.
* fir
* date arbitrare (date utilizator)
* masa

Dacă totul este clar cu primele tipuri, atunci ce sunt datele utilizatorului? Amintiți-vă că Lua este un limbaj încorporat și de obicei lucrează îndeaproape cu componentele programelor scrise în alte limbi. Deci, aceste componente „străine” pot crea date în funcție de nevoile lor și pot stoca aceste date împreună cu obiectele lua. Deci, userdata este partea subacvatică a aisbergului, care din punctul de vedere al limbajului lua nu este necesară, dar pur și simplu nu o putem ignora.

Și acum cel mai important lucru în limbă sunt tabelele.

Mese

Te-am mințit din nou când am spus că limbajul are 8 tipuri de date. Puteți presupune că el este unul: totul sunt mese (apropo, acest lucru nu este adevărat). Un tabel este o structură de date foarte elegantă, combină proprietățile unui tablou, un tabel hash ("cheie" - "valoare"), structură, obiect.

Deci, iată un exemplu de tabel ca matrice: a = (1, 2, 3) - o matrice de 3 elemente tipărite (a) - va scoate „2”, deoarece indicii sunt numărați de la unul - Un tabel este un matrice rară (care nu are toate elementele) a = () - tabel gol a = 1 a = 5

THINK: Ce este a pentru o matrice rară?

În exemplul de mai sus, tabelul se comportă ca o matrice, dar în realitate - avem chei (indici) și valori (elemente de matrice). Și, în același timp, cheile pot fi de orice tip, nu doar numere:

A = () a ["bună ziua"] = adevărat a ["lumea"] = fals a = 1 - sau astfel: a = (bună ziua = 123, lume = 456) print (a ["bună ziua")) imprimare ( a.hello) este la fel cu un ["hello"], deși arată ca o structură cu câmpuri

Apropo, deoarece tabelul are chei și valori, puteți trece peste toate cheile și valorile corespunzătoare într-o buclă:

T = (a = 3, b = 4) pentru cheie, valoare în perechi (t) do print (cheie, valoare) - afișează „a 3”, apoi „b 4” final

Dar cum rămâne cu obiectele? Vom afla despre ele puțin mai târziu, mai întâi - despre funcții.

Funcții

Iată un exemplu de funcție comună.

Funcția add (a, b) return a + b end print (adăugați (5, 3)) - va imprima „8”

Funcțiile limbajului vă permit să luați mai multe argumente și să returnați mai multe argumente. De exemplu, argumentele care nu sunt specificate în mod explicit sunt considerate a fi zero.

Gândiți-vă: De ce ați dori să returnați mai multe argumente?

Funcție swap (a, b) return b, a end x, y = swap (x, y) - apropo, acest lucru se poate face fără o funcție: x, y = y, x - și dacă funcția returnează mai multe argumente , - și nu aveți nevoie de ele - ignorați-le cu - variabilă specială de subliniere „_” a, _, _, d = some_function ()

Funcțiile pot lua un număr variabil de argumente:

În prototip, numărul variabil de argumente este scris ca funcția puncte suspensie sum (...) s = 0 pentru _, n în perechi (arg) do - în funcție sunt denumite tabelul „arg” s = s + n final returnează o sumă finală (1, 2, 3) - va returna 6 sumă (1, 2, 3, 4) - va returna 10

Deoarece funcțiile sunt un tip de date cu drepturi depline, puteți crea variabile de funcție sau puteți transmite funcții ca argumente altor funcții.

A = function (x) return x * 2 end - functie care se inmulteste cu 2 b = function (x) return x + 1 end - functie care creste cu 1 function apply (tabel, f) rezultat = () for k, v in perechile (tabelul) rezultă [k] = f (v) - înlocuiți elementul cu o funcție de la sfârșitul acestui element - Gândiți-vă: ceea ce numește t = (1, 3, 5) va returna se aplică (t, a) se aplică ( t, b)

Obiecte = funcții + tabele

Deoarece putem stoca funcții în variabile, atunci putem și în câmpurile de tabele. Și aceasta se dovedește deja, parcă, metode. Pentru cei care nu sunt familiarizați cu OOP, voi spune că principalul său beneficiu (cel puțin în Lua) este că funcțiile și datele cu care lucrează sunt una lângă alta - în cadrul aceluiași obiect. Pentru cei care sunt familiarizați cu OOP, voi spune că aici nu există clase, dar moștenirea este prototipică.

Să trecem la exemple. Avem un obiect, să zicem, un bec. Ea știe să ardă și să nu ardă. Ei bine, există două lucruri pe care le puteți face cu el - porniți-l și opriți-l:

Lampa = (on = false) function turn_on (l) l.on = true end function turn_off (l) l.on = false end sunt doar functii pentru lucrul cu structura turn_on (lampa) turn_off (lampa)

Și dacă transformăm becul într-un obiect și transformăm funcțiile turn_off și turn_on în câmpuri ale obiectului, obținem:

Lampa = (aprins = fals turn_on = function (l) l.on = true end turn_off = function (l) l.on = false end) lamp.turn_on (lamp) lamp.turn_off (lampa)

Suntem nevoiți să trecem obiectul bec în sine ca prim argument, pentru că altfel funcția noastră nu va ști cu ce bec trebuie să funcționeze pentru a schimba starea de pornire/oprire. Dar pentru a nu fi verborizat, Lua are o stenografie care se folosește de obicei - lamp: turn_on (). În total, știm deja câteva astfel de simplificări de sintaxă:

Lampă: turn_on () - cea mai comună notație lamp.turn_on (lamp) - din punct de vedere al sintaxei, aceasta este și lampă corectă ["turn_on"] (lamp) - și aceasta

Continuând să vorbim despre abrevieri, funcțiile pot fi descrise nu numai în mod explicit, ca câmpuri ale unei structuri, ci și într-o formă mai convenabilă:

Lampa = (on = fals) - printr-o punct, atunci argumentul trebuie specificat function lamp.turn_on (l) l.on = true end - prin doua puncte, apoi argumentul este implicit setat ca variabila "self" - "self " - și există lampa pentru care a fost numită lampa de funcție: turn_off () self.on = false end

Interesant?

Funcții speciale

Unele nume de funcții (metode) de tabel sunt rezervate și au o semnificație specială:

* __add (a, b), __sub (a, b), __div (a, b), __mul (a, b), __mod (a, b), __pow (a, b) - numit atunci când se efectuează operații aritmetice pe masa
* __unm (a) - operație unară în minus (când scriu ceva de genul „x = -x”)
* __lt (a, b), __le (a, b), __eq (a, b) - calculați rezultatul comparației (<, <=, ==)
* __len (a) - numit când „#a” este terminat
* __concat (a, b) - numit când „a..b”
* __call (a, ...) - numit când „a ()”. Argumentele variabile sunt argumente atunci când sunt apelate
* __index (a, i) - apel la un [i], cu condiția ca un astfel de element să nu existe
* __newindex (a, i, v) - creând „a [i] = v”
* __gc (a) - când un obiect este aruncat de colectarea gunoiului

Prin înlocuirea acestor metode, puteți supraîncărca operatorii și puteți utiliza sintaxa limbii în scopuri proprii. Principalul lucru este să nu exagerați.

Moştenire

Pentru cei care nu cunosc OOP, moștenirea vă permite să extindeți funcționalitatea unei clase existente. De exemplu, doar un bec se poate aprinde și stinge, iar un bec super-luminos își va schimba și luminozitatea. De ce trebuie să rescriem metodele turn_on / turn_off când le putem reutiliza?

Lua are conceptul de meta-tabel pentru aceasta, i.e. tabelele strămoșilor. Fiecare tabel are un tabel părinte, iar tabelul copil poate face tot ce poate face părintele.

Să presupunem că am creat deja obiectul de masă lampă. Atunci super becul va arăta astfel:

Superlamp = (luminozitate = 100) - specificați tabelul părinte setmetatable (superlamp, lampă) - iar metodele sale sunt acum disponibile superlamp: turn_on () superlamp: turn_off ()

Extinderea funcționalității

Există multe tipuri de tabele părinte (bine, șiruri și tabele, cu siguranță, numere și booleeni, iar nil nu). Să presupunem că vrem să adăugăm toate liniile folosind operatorul „+”, nu „..”. Pentru a face acest lucru, înlocuiți funcția „+” (__add) pentru tabelul părinte al tuturor rândurilor:

S = getmetatable ("") - a primit tabelul părinte al rândului s .__ add = function (s1, s2) return s1..s2 end - a schimbat metoda - verificați a = "hello" b = "world" print ( a + b) - va scrie „helloworld”

De fapt, încă putem înlocui funcția de imprimare cu „print = myfunction”, și se pot face multe alte lucruri de hacking.

Domenii de aplicare

Variabilele sunt globale și locale. Când sunt create, toate variabilele din Lua sunt globale.

Gândește-te: de ce?

Pentru a specifica domeniul local, scrieți cuvântul cheie local:

Local x local var1, var2 = 5, 3

Nu uita de acest cuvânt.

Eroare la procesare

Adesea, dacă apar erori, trebuie să opriți executarea unei anumite funcții. Puteți, desigur, să faceți o mulțime de verificări și să suni „retur” dacă ceva nu merge bine. Dar acest lucru va crește cantitatea de cod. Lua folosește ceva de genul excepțiilor.

Erorile sunt aruncate folosind funcția de eroare (x). Orice poate fi transmis ca argument (ceea ce este relevant pentru eroare - o descriere șir, un cod numeric, obiectul cu care a apărut eroarea etc.)

De obicei, după această funcție, întregul program se blochează. Și acest lucru nu este întotdeauna necesar. Dacă apelați o funcție care ar putea genera o eroare (sau funcțiile sale secundare ar putea genera o eroare), atunci apelați-o în siguranță folosind pcall ():

Funcția f (x, y) ... dacă ... atunci eroare („nu a reușit să facă ceva”) end... end status, err = pcall (f, x, y) - f: funcția, xy: argumentele sale dacă nu stare, atunci - gestionează eroarea err. În cazul nostru, err conține textul de eroare final

Biblioteci standard

Există multe biblioteci non-standard, acestea pot fi găsite pe LuaForge, LuaRocks și alte depozite.

Între Lua și Non-Lua

Și dacă funcționalitatea bibliotecilor standard nu este suficientă pentru noi? Ce se întâmplă dacă avem programul nostru C și vrem să-i apelăm funcțiile din Lua? Există un mecanism foarte simplu pentru asta.

Să presupunem că vrem să creăm propria noastră funcție care returnează un număr aleator (Lua are math.random (), dar vrem să învățăm). Va trebui să scriem următorul cod în C:

#include #include #include / * de fapt ce să faci când apelezi `rand (de la, la)` * / static int librand_rand (lua_State * L) (int from, to; int x; from = lua_tonnumber (L, 1); / * primul parametru al funcția * / la = lua_tonnumber (L, 2); / * al doilea parametru al funcției * / x = rand ()% (la - de la + 1) + de la; lua_pushnumber (L, x); / * returnează valoarea * / returnează 1; / * returnează doar un argument * /) / * în Lua „rand” corespunde funcției noastre librand_rand () * / static const luaL_reg R = ((„rand”, librand_rand), (NULL, NULL) / * end a listei de funcții exportate * / ); / * apelat când biblioteca este încărcată * / LUALIB_API int luaopen_librand (lua_State * L) (luaL_openlib (L, "librand", R, 0); srand (time (NULL)); return 1; / * succes * /)

Acestea. Lua ne oferă funcții pentru a lucra cu tipuri de date, pentru a primi argumente ale funcției și a returna rezultate. Funcțiile sunt puține și departe. Acum construim biblioteca noastră ca o bibliotecă dinamică și putem folosi funcția rand ():

Random = require ("librand") - încărcați biblioteca print (random.rand (1, 100)) print (random.rand (0, 1))

Ce se întâmplă dacă vrem să apelăm codul Lua din programele noastre? Apoi, programele noastre ar trebui să creeze o mașină virtuală Lua, în care vor fi executate scripturi Lua. E mult mai usor:

#include "lua.h" #include "lauxlib.h" int main () (lua_State * L = lua_open (); // creați o mașină virtuală Lua luaL_openlibs (L); // încărcați biblioteca standard luaL_dofile (L, " rand. lua "); // execută scriptul lua_close (L); // închide Lua return 0;)

Tot.

Acum poți scrie în Lua. Dacă aflați puncte interesante despre Lua care ar putea fi reflectate în articol - scrieți!

Această serie de tutoriale pe care am conceput-o va discuta despre limbajul de programare Lua. Voi încerca să fac prezentarea cât mai accesibilă pentru începători și mă voi concentra asupra lor. Adică, codificatorii Lua cu experiență, cel mai probabil, nu vor învăța nimic nou din asta (sunt sigur că vor găsi loc doar pentru cicăli și remarci, care, de fapt, sunt chiar binevenite din partea lor), dar dacă nu aveți bogați experiență de programare în spatele tău, atunci cred că te poți descurca cu ceva.

Întreaga serie nu se va supune niciunui sistem. Lecțiile vor introduce secvenţial un număr de constructe de limbaj, astfel încât până la a treia sau a patra lecție să vă puteți scrie deja programele. Scopul meu este să te împing să înveți limba pe cont propriu, să te ajut să o simți, și nu să o explic de la A la Z - dacă vrei să stăpânești limba complet, citește manualul de referință (care, deși prost, este tradus în rusă: http: //www.lua .ru / doc /). Cu cât treci mai repede de la lecțiile „pentru manechin” de pe web pentru a studia ghidul, cu atât mai bine.

Dacă ceva nu este clar - asigurați-vă că puneți o întrebare în comentarii, iar eu și alți membri vom încerca să vă ajutăm.

Lua este un limbaj de programare de uz general popular, ușor de învățat, încorporabil, interpretat, tipizat dinamic. Nu, nu trebuie să înțelegeți nici măcar jumătate din cuvintele din propoziția anterioară - principalul lucru este să știți că este popular și necomplicat. Apropo, și-a câștigat popularitatea datorită simplității și dimensiunii mici a kitului de distribuție (aproximativ 150 de kiloocteți). Scripturile Lua sunt acceptate de un număr mare de aplicații, inclusiv jocuri. World of Warcraft și S.T.A.L.K.E.R. folosește limba Lua. Motorul meu de joc preferat vă va permite să creați o varietate de jocuri cu ușurință folosind Lua. După cum poți vedea, Lua îți deschide o mulțime de orizonturi!

Înainte de a începe, trebuie să configurați un mediu de programare: adică să găsiți un program care acceptă și execută codul Lua pe care îl scrieți: un interpret. Există trei opțiuni aici:

1. Descărcați distribuția oficială Lua de pe unul dintre site-urile care le furnizează.

Doar codul sursă al interpretului poate fi descărcat de pe site-ul oficial Lua. Cu toate acestea, examinând http://lua.org/download.html în secțiunea Binare, este posibil să găsiți link-uri către site-uri cu fișiere executabile pentru Windows. Unul din ei: . Descărcați de acolo una dintre arhive (care se potrivește cu platforma dvs.: Win32 sau Win64) și despachetați-o undeva, de preferință într-un director cu o cale scurtă: cum ar fi C: \ lua. De acum înainte, voi presupune că utilizați Windows și interpretul dvs. este acolo.

Utilizatorii sistemelor de operare bazate pe Linux sunt mai ușori în acest sens: trebuie doar să folosească managerul de pachete și să instaleze Lua din depozite. Pe Debian și Ubuntu, acest lucru se face cu apt-get install lua, iar pe Fedora, Red Hat și derivate, se face cu yum install lua. Cu toate acestea, nu aveți încredere orbește în mine și consultați manualul sistemului de operare pentru a afla exact cum faceți acest lucru.

2. Folosiți un interpret online.

Situat la http://www.lua.org/demo.html. La început, poate fi suficient, dar mai târziu, când vom atinge module, va trebui să utilizați versiunea offline. Utilizarea interpretului online este foarte simplă: introduceți programul dvs. în fereastra cu text și faceți clic pe butonul Run. Programul va fi executat, fereastra Ieșire va afișa rezultatul programului dvs., precum și rapoarte de eroare, dacă există.

3. Utilizați IDE.

De exemplu, ZeroBrane Studio: http://studio.zerobrane.com/. Mai sunt și altele - căutați pe internet.

Există acum două versiuni ușor diferite de Lua în circulație: 5.1 și 5.2. Mă voi concentra pe cea mai recentă versiune - versiunea 5.2, dar cu siguranță voi sublinia diferențele importante dintre aceasta și 5.1, deoarece și cea din urmă este destul de comună. Apropo, Lua 5.1 execută codul de o dată și jumătate mai rapid decât Lua 5.2, așa că știi.

=== Lecția # 1 ===

Deci, să începem. Creați un fișier main.lua într-un folder izolat de fișierele străine și scrieți în el:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
- main.lua -
tipăriți ("Bună lume!")

Apoi rulați pe linia de comandă (nu uitați să vă mutați în directorul cu main.lua folosind comanda cd):

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

Ca răspuns, interpretul Lua va emite:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
Salut Lume!

În principiu, acest lucru era de așteptat. În program, am numit funcția de imprimare. Funcția de imprimare preia un număr arbitrar de parametri și îi imprimă secvenţial pe ecran. În acest exemplu, i-am trecut șirul (șirul de caractere) „Hello world!” Puteți trece la fel de bine ca parametru:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
print (8) - un număr zecimal
- va ieși: 8

Imprimare (0xDEADBEEF) - număr hexazecimal
- va ieși: 3735928559

Print ("0xDEADBEEF") este un șir, nu un număr! Vedeți ghilimele?
- va scoate: 0xDEADBEEF

Imprimare (1.35e-4) - număr în virgulă mobilă (număr fracționar)
- Va scoate 0,000135. 1.35e-4 ar trebui înțeles ca „1,35 înmulțit
- cu zece până la minus al patrulea grad”, dacă cineva nu știe.

Imprimare ((198 * 99) -3 * 500 + 14/88) - expresie
- Va afișa valoarea expresiei: 18102.159090909. Nu este o alternativă rea
- un calculator desktop!

Imprimare (198/7, „îngrășământ”, 2 ^ 9) - câțiva parametri ai unui arbitrar
- tip. Se vor afișa valorile fiecăruia dintre ele, separate prin semne
- file:
- 28.285714285714 ingrasamant 512
- Vă rugăm să rețineți că ghilimele în jurul îngrășământului nu sunt afișate!

Print (1,35) este două numere, nu o fracție zecimală de 1,35!
- O virgulă este folosită pentru a separa parametrii.
- Va scoate:
-- 1 35

Semnul „-” nu este doar o imitație a liniuței, care este inserată pentru frumusețe. Semnul „-” în Lua denotă comentarii: indicii pentru programator care sunt ignorate de interpret și menite să facă codul mai ușor de înțeles. Puteți încerca să scrieți în program:

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

Interpretul va crede că este un comentariu și nu va urma instrucțiunile.

Notă pentru gazdă: dacă doriți să imprimați o singură linie, puteți scrie apelul de tipărire astfel, fără paranteze:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
imprimați „Doar un șir”

Comoditatea este cu siguranță discutabilă: rețineți că este posibil. Cu toate acestea, astfel de apeluri sunt inacceptabile:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
print 2 - nu va funcționa, 2 - nu este un șir.
imprimați 2 * 2 + 6 - în plus, nu va funcționa

Str = "șir!!" - a atribuit variabilei str valoarea "șir !!"
- citiți mai jos despre variabile
nici print str nu va funcționa.

În fiecare dintre cazurile de mai sus, programul va refuza pur și simplu să funcționeze. Astfel, într-un apel „fără părinte”, un nume de funcție poate fi urmat doar de un șir literal (adică o secvență de caractere cuprinse între ghilimele) și nimic altceva. În viitor, voi vorbi despre această funcție mai detaliat, dar deocamdată este suficient pentru tine.

În orice limbaj de programare bun, este posibil să se declare variabile: containere mici care pot conține unele date. Lua procedează astfel:

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

De exemplu:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
steaua = 8 - Steaua variabilă stochează acum numărul 8
wars = „bufniță” - Variabila wars conține șirul „bufniță”
jedi = 42/2 - În jedi variabil - numărul 21
luke = star * jedi - Variabila luke este numărul 168 (da, de 21 ori 8)

De asemenea, pot fi afișate valorile variabilelor și expresiile cu acestea:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
imprimare (star, wars, jedi, jedi-star + luke)
- Va scoate:
- 8 bufniță 21 181

Doar nu încercați să adăugați variabilele star and wars - încercarea de a adăuga 8 la „bufniță” nu vă va ajuta la nimic!

După cum ar fi trebuit să observați, numele unei variabile poate fi aproape orice: principalul lucru este că nu începe cu un număr. Serios, puteți chiar să declarați o variabilă numită print, iar apoi funcția de imprimare nu va mai funcționa, deoarece numele print se va referi la variabila nou declarată. Dar există un grup de cuvinte care sunt interzise să fie folosite ca nume de variabile - acestea sunt cuvinte cheie de limbă pe care nu le-am întâlnit încă, dar care merită cu siguranță să le vedem:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
și break do elseif end
false pentru funcția goto if in
local nul nu sau returnare repetă
atunci adevărat până când

Prin crearea unei variabile cu unul dintre aceste nume, veți provoca o eroare în program și cu siguranță nu va funcționa. Vă rugăm să rețineți că în Lua 5.1 nu există un cuvânt cheie goto și puteți numi o variabilă în acest fel, dar mai bine nu faceți asta.
De asemenea, rețineți că numele variabilelor țin cont de majuscule și minuscule. Aceasta înseamnă că foo, fOo, fOO și FOO sunt patru variabile diferite, așa că dacă ați scris numele unei variabile cu litere mici și mai târziu ați scris-o cu majuscule, atunci cel mai probabil programul nu va funcționa corect.

Acum, pentru un punct important: ce se întâmplă dacă, din întâmplare sau intenționat, te referi la o variabilă inexistentă? În majoritatea celorlalte limbi, acest lucru va provoca o eroare, dar în Lua această situație este acceptabilă. Este interpretată ca și cum o variabilă inexistentă ar exista de fapt, dar valoarea ei este zero. zero- amintește-ți acest cuvânt! este un tip de valoare specială în Lua care înseamnă „nimic”. Nu un zero sau un șir gol (un șir ca „” - încercați să îl afișați), dar pur și simplu nimic. Compară asta cu acest model: sunt două persoane, una dintre ele are un cont bancar, dar nu există bani pe el, iar cealaltă nu are cont bancar deloc. În termeni Lua, se va considera că primul are 0 dolari în cont, iar al doilea are zero... Și nici măcar dolari, ci doar zero... Sper că nu te-am încurcat.

Încercați, de exemplu, să rulați un program ca acesta:

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
- main.lua -
foo = "bar"
print (foo, baz)
- Va scoate:
- bar nul

Astfel, variabila baz, care nu există, dar se presupune că este, are valoarea nul, iar funcția de imprimare înțelege acest lucru și o tipărește pe ecran ca șirul „nil”. Lua are o metodă bună de verificare a existenței unei variabile: dacă valoarea unei variabile nu este zero, atunci aceasta este cel puțin declarată. Alternativ, puteți declara în mod explicit o variabilă ca fiind zero:

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

Acest lucru se poate face și, deși poate părea o prostie la prima vedere, uneori se face. În lecțiile ulterioare, vei afla cine și de ce și probabil vei începe să faci același lucru. Uneori, desigur.
Ai grijă cu nil: poți tipări nil, dar nu poți face aritmetică cu el! Adică dacă scapi cu print (nil), atunci o construcție ca 99 + nil va arunca o eroare, chiar dacă ai dori 99+ nil a egalat 99. Crede-mă, am fost și eu supărat când am aflat.

Rezumat:
1. Am învățat despre funcția de imprimare, ce poate face și cum să o numim corect fără paranteze.
2. A învățat cum să declari variabile, cum să calculezi expresii (deși destul de puțin), ce nume pot fi variabilele.
3. A învățat despre nil, a pătruns cu misterul său mistic și a câștigat încrederea că în viitor vom fi asociați cu o mulțime de el.

Pentru cei care sunt curioși și care doresc să-și consolideze cunoștințele, le ofer exerciții simple, pe care o puteți sări dacă vă simțiți deja suficient de competent:
1. Scrie un program care redă refrenul cântecului tău preferat.
2. Încercați să scoateți valorile următoarelor expresii. Încercați să înțelegeți de ce unele dintre ele funcționează și altele nu. Uitați-vă la erorile cauzate de expresiile eșuate.

200? "200px": "" + (this.scrollHeight + 5) + "px"); ">
2 + „șir”;
6 + "14";
„cutie” - „vox”;
1 * „11b”
„148” * „1e6”;


3. Scrieți un program care schimbă două variabile. Acesta este:

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


Faceți ca a să devină egal cu 8086 și b egal cu 6502. Pentru a face acest lucru, creați o a treia variabilă și efectuați câteva schimburi simple. Asigurați-vă că problema este rezolvată corect apelând print (a, b) înainte de schimb și print (a, b) după.

Ți-a plăcut articolul? Împărtășește-l