Cum se configurează smartphone-uri și PC-uri. Portal informativ
  • Acasă
  • Fier
  • Limbajul de programare Rust. Prezentare generală a limbajului de programare Rust

Limbajul de programare Rust. Prezentare generală a limbajului de programare Rust

În 2013, Mozilla, împreună cu Samsung, au anunțat dezvoltarea unui nou motor de browser web, Servo. A fost creat special pentru procesoarele multi-core ale dispozitivelor mobile, este capabil să despartă sarcinile în fire paralele și să reducă foarte mult timpul de încărcare a paginilor web. Servo este scris în întregime în limbajul de programare Rust, pe care Mozilla l-a dezvoltat pentru scrierea aplicațiilor mobile.

Despre limbaj

Rust este un limbaj de programare procedural care acceptă o varietate de stiluri de codare. Dezvoltatorul Graydon Hoare a început să creeze limbajul în 2006, iar trei ani mai târziu, Mozilla s-a alăturat proiectului. În 2010, Rust a fost prezentat la conferința Mozilla Summit. În același an, dezvoltarea a fost transferată la un compilator scris în Rust. Compilatorul a folosit ca bază de date sistemul universal de analiză și transformare a programelor LLVM.

Prima versiune stabilă a limbii a fost lansată în 2015. După lansarea versiunii alfa, Rust a suferit modificări - în compilator au rămas doar caracteristici gata făcute care nu se vor schimba. Orice altceva a fost mutat în secțiunea experimentală.

În centrul limbajului, Graydon Hoare a stabilit concepte precum:

  • Siguranță. Rust conține o serie de restricții de programare care sunt activate implicit. Pentru a le dezactiva, eticheta „nesigur” este necesară în blocuri și funcții.
  • Viteză. Limbajul este comparabil ca viteză cu un alt limbaj de programare, C++, care oferă un număr clar de avantaje pentru programator.
  • Paralelism. Sistemul poate efectua mai multe calcule simultan și, în același timp, pot interacționa între ele.
  • Concizie. Primele cuvinte cheie din Rust au fost limitate la cinci caractere. Dar mai târziu această restricție a fost ridicată.

Un exemplu de unul dintre primele coduri din Rust

Cu toate acestea, Rust nu este lipsită de dezavantaje, dintre care cele mai izbitoare sunt:

  • Redundanța codului.
  • Lipsa literaturii pentru învățarea limbilor străine.
  • Claritate în introducerea parametrilor de compilare. Acest lucru nu se potrivește întotdeauna programatorilor experimentați, deoarece alte limbi nu au reguli similare.

Cu toate acestea, limba este modernizată și extinsă în mod regulat: actualizările sale sunt lansate la fiecare 6 săptămâni.

Comparând Rust cu C++

Creatorii Rust îl consideră succesorul C++, care a apărut la începutul anilor 1980, când dezvoltatorul a venit cu câteva îmbunătățiri ale limbajului C. Prin urmare, merită să comparăm limbajul tânăr și încă în schimbare cu cel testat în timp.

  • Accesarea memoriei de la distanță. În C++, ștergerea unei variabile poate cauza o serie de probleme. Astfel de complicații nu sunt posibile în Rust, deoarece nu are comenzi pentru ștergerea memoriei. Compilatorul descendent va raporta că codul pe care l-ați scris conține o eroare, iar compilatorul C++ va scoate rezultatul fără valorile eliminate, fără a raporta măcar problema.
  • Punct şi virgulă. Adăugarea unui punct și virgulă suplimentar la codul dvs. va provoca o eroare în C++, în timp ce în Rust corpul buclei este închis între acolade.
  • Cod nesigur. Rust are o etichetă „nesigur” care izolează codul principal de codul nesigur. În viitor, atunci când revizuiți codul, acest lucru vă permite să restrângeți căutarea vulnerabilităților.

Firefox a fost implementat în C++: acest limbaj capricios necesita o atenție sporită la detalii. În caz contrar, erorile s-au transformat în vulnerabilități grave. Rust a fost conceput pentru a rezolva această problemă.

Perspective

În clasamentul RedMonk pentru al treilea trimestru din 2018, limbajul de programare Mozilla ocupă în mod constant locul 23. Experții consideră că poziția sa nu este în pericol de a se îmbunătăți. În ciuda acestui fapt, în august 2018, creatorii au lansat Rust 1.28 actualizat.

După lansarea Rust în 2015, potrivit Stack Overflow, 74% dintre dezvoltatori au dorit să se familiarizeze cu acesta. Cu toate acestea, deja în 2016, a trecut pe primul loc: 79% dintre utilizatori au numit Rust drept limbajul lor de programare preferat și și-au exprimat dorința de a continua să lucreze cu el. Rugina a ocupat primul loc în acest parametru în 2018.

Stack Overflow este un sistem popular de întrebări și răspunsuri de programare dezvoltat în 2008.

Popularitatea Rust este confirmată de numărul de companii care îl folosesc în dezvoltarea lor. În prezent, această listă include 105 organizații.

Așadar, am dori să vă prezentăm un băiat de naștere recent (a împlinit un an pe 15 mai 2016) - Rust. Acesta este un limbaj de programare universal dezvoltat de Mozilla, ale cărui trei principii principale sunt: ​​viteza, securitatea și ergonomia. Creatorii înșiși îl consideră fără modestie unul dintre cei mai probabili succesori ai C/C++. Potrivit unui sondaj pe StackOverflow, Rust este limbajul cel mai preferat printre dezvoltatori de astăzi. Deci, să aruncăm o privire mai atentă la ce este.

Rugină pentru un începător

Nu vreau să înșel pe nimeni, așa că iată o declarație responsabilă: Rugina este destul de greu de învățat. În primul rând, acest lucru se datorează tinereții limbii și, în consecință, cantității mici de literatură. În al doilea rând, poate fi și mai ușor pentru o persoană departe de a programa să o învețe decât pentru cineva familiarizat cu alte limbi. Deci, de exemplu, un specialist IT gata făcut va fi foarte enervat de necesitatea de a prescrie cele mai mici operații, iar absența moștenirii ca atare în limbă îl va deruta pur și simplu.

Cu toate acestea, Rust se dezvoltă rapid (o nouă ediție este lansată la fiecare 6 săptămâni), comunitatea crește, iar găsirea de informații pe Internet nu mai este dificilă.

Cum să studiezi

Puteți găsi aproape tot ce aveți nevoie pe site-ul oficial. În plus, comunitatea adepților Rust este foarte mare și prietenoasă, așa că poți oricând să apelezi la IRC (există o secțiune rusă) și la forumul oficial pentru sfaturi. În plus, cărțile, inclusiv cele electronice, au început să apară încetul cu încetul. Este încă dificil de evaluat calitatea lor, dar acesta este un fapt.

Pentru cei care au trecut de etapa inițială de cunoaștere, puteți găsi o mulțime de material util pe GiHub, inclusiv RFC-uri și commit-uri. În plus, puteți participa personal sau măcar urmăriți webcast-ul uneia dintre conferințele Rust programate pentru a doua jumătate a anului. Iată calendarul:

  • 9-10 septembrie conferința RustConf în Portland, SUA;
  • 17 septembrie, Conferința Comunităților Europene RustFest de la Berlin, Germania;
  • 27 octombrie Conferința Rust Belt Rust din Pittsburgh, SUA;

Ei bine, pentru a-i întâlni pe cei care consideră că Rust sunt chemarea lor și, în același timp, să le ceri toată înțelepciunea lor, puteți contacta organizatorii și participanții la întâlnirile fanilor limbilor de la Moscova.

Particularități

Duplicând puțin ceea ce s-a spus mai devreme, vom evidenția principalele avantaje și dezavantaje ale limbajului Rust.

Pro:

  • Lucru sigur cu memorie;
  • Performanta ridicata;
  • tip de date algebrice;
  • Previzibilitatea compilarii;

Minusuri:

  • O anumită redundanță de cod;
  • Intensitate mare a dezvoltării limbajului și, în consecință, lipsa unei literaturi adecvate pentru studiu;
  • Necesitatea de a specifica clar și fără ambiguitate parametrii pentru compilare.

De fapt, te obișnuiești rapid cu diferențele, cum ar fi înlocuirea moștenirii cu abilități. De îndată ce ochii tăi se obișnuiesc și mâinile tale se obișnuiesc, Rust se transformă într-un limbaj complet de lucru, mai simplu și mai funcțional decât C++, dar inferior în „frumusețe” multor alte limbaje de programare. De fapt, principala diferență dintre Rust și concurenții și predecesorii săi este viteza și securitatea.

Cerere

Astăzi, Rust este popular printre dezvoltatorii de jocuri, grafică și sisteme de operare. Cu toate acestea, din motive evidente, numărul de locuri staționare în care sunt necesari experți înalt specializați în rugină este extrem de mic în lume și cu atât mai mult în Rusia. Cu toate acestea, încă nu există semne că limbajul se va scufunda în uitare; arată mai mult ca o preluare sistematică a lumii. Aceasta înseamnă că abilitățile bune în utilizarea Rust în viitor vă vor ajuta să găsiți un loc de muncă bine plătit, interesant atât în ​​țara noastră, cât și în străinătate.

Încă la cerere: profesie „”.

Rugini este un nou limbaj de programare experimental dezvoltat de Mozilla. Limbajul este compilat și multi-paradigma, poziționat ca o alternativă la C/C++, ceea ce în sine este interesant, deoarece nu există nici măcar atât de mulți concurenți la competiție. Vă puteți aminti D-ul lui Walter Bright sau Go-ul lui Google.
Rust acceptă programarea funcțională, paralelă, procedurală și orientată pe obiecte, de ex. aproape întreaga gamă de paradigme utilizate efectiv în programarea aplicaţiilor.

Scopul meu nu este să traduc documentația (în plus, este foarte puțină și este în continuă schimbare, deoarece nu a existat încă o lansare oficială a limbii), ci vreau să evidențiez cele mai interesante caracteristici ale limbii. Informațiile au fost culese atât din documentația oficială, cât și din extrem de puținele mențiuni ale limbii de pe internet.

Prima impresie

Sintaxa limbajului este construită într-un stil tradițional asemănător C (ceea ce este o veste bună, deoarece acesta este deja un standard de facto). Desigur, au fost luate în considerare binecunoscutele erori de proiectare C/C++.
O lume tradițională Hello World arată astfel:
utilizați std; fn main(args: ) ( std::io::println("bună lumea din " + args + "!"); )

Un exemplu puțin mai complicat - funcția de calcul factorial:

Fn fac(n: int) -> int (fie rezultat = 1, i = 1; în timp ce i<= n { result *= i; i += 1; } ret result; }

După cum puteți vedea din exemplu, funcțiile sunt declarate în stilul „funcțional” (acest stil are unele avantaje față de tradiționalul „int fac(int n)”). V-om vedea inferență de tip automat(cheie cheie let), fără paranteze în argumentul while (la fel ca Go). Un alt lucru care vă atrage imediat atenția este compactitatea cuvintelor cheie. Creatorii lui Rust și-au propus să păstreze toate cuvintele cheie cât mai scurte posibil și, să fiu sincer, îmi place.

Caracteristici sintactice mici, dar interesante

  • Puteți introduce liniuțe de subliniere în constante numerice. Aceasta este o caracteristică utilă; această caracteristică este acum adăugată în multe limbi noi.
    0xffff_ffff_ffff_ffff_ffff_ffff
  • Constante binare. Desigur, un programator adevărat trebuie să transforme bin în hex în capul său, dar este mai convenabil în acest fel! 0b1111_1111_1001_0000
  • Corpurile oricăror declarații (chiar și cele care constau dintr-o singură expresie) trebuie să fie închise între acolade. De exemplu, în C ai putea scrie if(x>0) foo(); , în Rust trebuie să puneți bretele în jurul foo()
  • Dar argumentele operatorilor if, while și similari nu trebuie să fie incluse în paranteze
  • în multe cazuri, blocurile de cod pot fi considerate expresii. În special, sunt posibile următoarele:
    fie x = if the_stars_align() ( 4 ) else if something_else() ( 3 ) else ( 0 );
  • sintaxa declarației funcției - mai întâi cuvântul cheie fn, apoi o listă de argumente, tipul argumentului este indicat după nume, apoi, dacă funcția returnează o valoare, o săgeată „->” și ​​tipul valorii returnate
  • Variabilele sunt declarate în același mod: cuvântul cheie let, numele variabilei, după variabilă se poate specifica tipul prin două puncte și apoi se atribuie o valoare inițială.
    lasă să numere: int = 5;
  • În mod implicit, toate variabilele sunt imuabile; Cuvântul cheie mutabil este folosit pentru a declara variabile mutabile.
  • numele tipurilor de bază sunt cele mai compacte dintre toate pe care le-am întâlnit: i8, i16, i32, i64, u8, u16, u32, u64,f32, f64
  • după cum sa menționat mai sus, este acceptată inferența de tip automat
Limbajul are încorporate instrumente de depanare a programelor:
Cuvânt cheie eșueazăîncheie procesul curent
Cuvânt cheie Buturuga scoate orice expresie de limbă în jurnal (de exemplu, la stderr)
Cuvânt cheie afirma verifică expresia și dacă este falsă, încheie procesul curent
Cuvânt cheie Notă vă permite să afișați informații suplimentare în cazul încetării anormale a procesului.

Tipuri de date

Rugina, ca Go, suportă tipărirea structurală(deși, conform autorilor, limbile s-au dezvoltat independent, deci aceasta este influența predecesorilor lor comuni - Alef, Limbo etc.). Ce este tiparea structurală? De exemplu, aveți o structură declarată într-un fișier (sau, în terminologia Rust, o „înregistrare”)
tip point = (x: float, y: float);
Puteți declara o mulțime de variabile și funcții cu tipuri de argumente „punct”. Apoi, în altă parte, puteți declara o altă structură, cum ar fi
tastați MySuperPoint = (x: float, y: float);
iar variabilele de acest tip vor fi pe deplin compatibile cu variabilele de tip punct.

În schimb, tastarea nominativă adoptată în C, C++, C# și Java nu permite astfel de construcții. Cu tastarea nominativă, fiecare structură este un tip unic, incompatibil implicit cu alte tipuri.

Structurile din Rust sunt numite „înregistrări”. Există și tupluri - acestea sunt aceleași înregistrări, dar cu câmpuri fără nume. Elementele unui tuplu, spre deosebire de elementele unei înregistrări, nu pot fi modificabile.

Există vectori - în unele moduri similare cu matricele obișnuite și în unele fel similare cu tipul std::vector de la stl. La inițializarea cu o listă, se folosesc paranteze drepte, nu paranteze ca în C/C++

Fie myvec = ;

Un vector, totuși, este o structură de date dinamică; în special, vectorii suportă concatenarea.

Fie v: mutabil = ; v += ;

Există șabloane. Sintaxa lor este destul de logică, fără aglomerație de „șablon” din C++. Șabloanele de funcții și tipuri de date sunt acceptate.

Fn pentru_rev (v: [T], act: bloc(T)) ( fie i = std::vec::len(v); în timp ce i > 0u ( i -= 1u; act(v[i]); ) ) tip circular_buf = (start: uint, end: uint, buf: );

Limba suportă așa-numitele Etichete. Aceasta nu este altceva decât o unire din C, cu un câmp suplimentar - codul variantei folosite (adică ceva în comun între o unire și o enumerare). Sau, din punct de vedere teoretic, un tip de date algebrice.

Forma etichetei (cerc (punct, plutitor); dreptunghi (punct, punct); )

În cel mai simplu caz, o etichetă este identică cu o enumerare:

Tag animal ( câine; pisică; ) let a: animal = câine; a = pisica;
În cazuri mai complexe, fiecare element al „enumerării” este o structură independentă care are propriul „constructor”.
Un alt exemplu interesant este o structură recursivă care este folosită pentru a defini un obiect de tip „listă”:
lista de etichete ( nul; contra (T, @list ); ) lasă a: listă = cons(10, @cons(12, @nil));
Etichetele pot participa la expresii de potrivire a modelelor, care pot fi destul de complexe.
alt x ( cons(a, @cons(b, _)) ( process_pair(a,b); ) cons(10, _) ( process_ten(); ) _ ( fail; ) )

Potrivire de model

Pentru început, putem considera modelul de potrivire ca un comutator îmbunătățit. Este folosit cuvântul cheie alt, urmat de expresia analizată și apoi în corpul declarației - modele și acțiuni dacă modelele se potrivesc.
alt numărul_meu ( 0 ( std::io::println("zero"); ) 1 | 2 ( std::io::println("unul sau doi"); ) 3 la 10 ( std::io::println ("de la trei la zece"); ) _ ( std::io::println ("altceva"); ) )
Ca „modele” puteți utiliza nu numai constante (ca în C), ci și expresii mai complexe - variabile, tupluri, intervale, tipuri, substituenți ("_"). Puteți specifica condiții suplimentare utilizând instrucțiunea when imediat după model. Există o variantă specială a operatorului pentru potrivirea tipului. Acest lucru este posibil deoarece limbajul are un tip de variantă universală orice, ale căror obiecte pot conține valori de orice tip.

Indicatori.În plus față de indicatoarele „C” obișnuite, Rust acceptă indicatoare „inteligente” speciale cu numărătoare de referințe încorporată - partajate (cutii partajate) și unice (cutii unice). Ele sunt oarecum similare cu shared_ptr și unique_ptr din C++. Au propria lor sintaxă: @ pentru partajat și ~ pentru unic. Pentru indicatori unici, în loc de copiere, există o operație specială - mutarea:
fie x = ~10; lasa y<- x;
După o astfel de mișcare, indicatorul x este deinițializat.

Închideri, aplicații parțiale, iteratoare

Aici începe programarea funcțională. Rust susține pe deplin conceptul de funcții de ordin superior, adică funcții care pot lua alte funcții drept argumente și le pot returna.

1. Cuvânt cheie lambda folosit pentru a declara o funcție imbricată sau un tip de date funcțional.

Fn make_plus_function(x: int) -> lambda(int) -> int ( lambda(y: int) -> int ( x + y ) ) let plus_two = make_plus_function(2); assert plus_doi(3) == 5;

În acest exemplu, avem o funcție make_plus_function care ia un argument „x” de tip int și returnează o funcție de tip „int->int” (lambda este cuvântul cheie aici). Corpul funcției descrie chiar această funcție. Lipsa unui operator „retur” este puțin confuză, dar acesta este un lucru obișnuit pentru FP.

2. Cuvânt cheie bloc folosit pentru a declara un tip funcțional - un argument de funcție, care poate fi înlocuit cu ceva similar cu un bloc de cod obișnuit.
fn map_int(f: block(int) -> int, vec: ) -> ( fie rezultat = ; pentru i in vec ( rezultat += ; ) ret rezultat; ) map_int((|x| x + 1 ), );

Aici avem o funcție a cărei intrare este un bloc - în esență o funcție lambda de tip „int->int”, și un vector de tip int (mai multe despre sintaxa vectorilor mai târziu). „Blocul” în sine este scris în codul de apel folosind o sintaxă oarecum neobișnuită (|x| x + 1). Personal, prefer lambdas în C#, simbolul | perceput în mod persistent ca SAU pe biți (care, apropo, este prezent și în Rust, ca toate operațiunile vechi bazate pe C).

3. Aplicarea parțială este crearea unei funcții bazată pe o altă funcție cu mai multe argumente prin specificarea valorilor unora dintre argumentele acelei alte funcții. Cuvântul cheie folosit pentru aceasta este legași un caracter substituent „_”:

Fie daynum = bind std::vec::position(_, ["mo", "tu", "we", "do", "fr", "sa", "su"])

Pentru a fi mai clar, voi spune imediat că acest lucru se poate face în C obișnuit prin crearea unui înveliș simplu, ceva de genul acesta:
const char* daynum (int i) ( const char *s =("mo", "tu", "we", "do", "fr", "sa", "su"); return s[i]; )

Dar aplicarea parțială este un stil funcțional, nu procedural (apropo, din exemplul dat nu este clar cum se face o aplicație parțială pentru a obține o funcție fără argumente)

Un alt exemplu: funcția add este declarată cu două argumente int, returnând int. În continuare, este declarat tipul funcțional single_param_fn, care are un argument int și returnează int. Folosind bind, sunt declarate două obiecte funcție add4 și add5, construite pe baza funcției add, care are argumente parțial specificate.

Fn add(x: int, y: int) -> int ( ret x + y; ) tip single_param_fn = fn(int) -> int; let add4: single_param_fn = bind add(4, _); let add5: single_param_fn = bind add(_, 5);

Obiectele funcție pot fi apelate în același mod ca și funcțiile obișnuite.
afirmă (adaugă(4,5) == adaugă4(5)); afirmă (adaugă(4,5) == adaugă5(4));

4. Funcții și predicate pure
Funcțiile pure sunt funcții care nu au efecte secundare (inclusiv cele care nu apelează la alte funcții cu excepția celor pure). Astfel de funcții sunt identificate prin cuvântul cheie pur.
pur fn lt_42(x: int) -> bool ( ret (x< 42); }
Predicatele sunt funcții pure care returnează tipul bool. Asemenea funcții pot fi utilizate în sistemul typestate (vezi mai jos), adică apelate în etapa de compilare pentru diverse verificări statice.

Macro-uri sintactice
O caracteristică planificată, dar foarte utilă. Este încă în dezvoltare timpurie în Rust.
std::io::println(#fmt(„%s este %d”, „răspunsul”, 42));
O expresie similară printf de la C, dar executată în timpul compilării (în consecință, toate erorile de argument sunt detectate în etapa de compilare). Din păcate, există foarte puține materiale despre macrocomenzi sintactice și ele însele sunt în curs de dezvoltare, dar există speranță că se va dovedi ceva ca macrocomenzile Nemerle.
Apropo, spre deosebire de Nemerle, consider că decizia de a evidenția macrocomenzile sintactic folosind simbolul # este foarte inteligentă: o macrocomandă este o entitate care este foarte diferită de o funcție și cred că este important să vedem la prima vedere unde este funcțiile de cod sunt numite și unde - macro-uri.

Atribute

Un concept similar cu atributele C# (și chiar cu sintaxă similară). Mulțumiri speciale dezvoltatorilor pentru acest lucru. După cum v-ați aștepta, atributele adaugă meta informații la entitatea pe care o adnotă.
# fn register_win_service() ( /* ... */ )
S-a inventat o altă variantă de sintaxă a atributelor - aceeași linie, dar cu punct și virgulă la sfârșit, adnotă contextul actual. Adică, ceea ce se potrivește cu bretele cele mai apropiate care includ un astfel de atribut.
fn register_win_service() ( #; /* ... */ )

Calcul paralel

Poate una dintre cele mai interesante părți ale limbii. În același timp, momentan nu este descris deloc în tutorial :)
Un program Rust constă dintr-un „arborele de sarcini”. Fiecare sarcină are o funcție de intrare, propria sa stivă, mijloace de interacțiune cu alte sarcini - canale pentru informațiile de ieșire și porturi pentru informațiile de intrare și deține unele dintre obiectele din heap-ul dinamic.
Mai multe sarcini Rust pot exista într-un singur proces de sistem de operare. Sarcinile Rust sunt „ușoare”: fiecare sarcină consumă mai puțină memorie decât procesul de sistem de operare, iar comutarea între ele este mai rapidă decât comutarea între procesele de sistem de operare (aici, probabil, ne referim la „fileuri”).

O sarcină constă din cel puțin o funcție fără argumente. Sarcina este lansată utilizând funcția de spawn. Fiecare sarcină poate avea canale prin care transmite informații către alte sarcini. Un canal este un tip de șablon special chan, parametrizat de tipul de date al canalului. De exemplu, chan este un canal pentru transmiterea octeților nesemnați.
Pentru a trimite către un canal, utilizați funcția de trimitere, al cărei prim argument este canalul, iar al doilea este valoarea care trebuie trimisă. Această funcție plasează de fapt valoarea în bufferul intern al canalului.
Porturile sunt folosite pentru a primi date. Un port este un tip de port generic, parametrizat de un tip de date de port: port este un port pentru primirea octeților nesemnați.
Pentru a citi din porturi, utilizați funcția recv, al cărei argument este portul și valoarea returnată sunt datele din port. Citirea blochează sarcina, de exemplu. dacă portul este gol, sarcina intră în starea de așteptare până când o altă sarcină trimite date către canalul asociat portului.
Asocierea canalelor cu porturi este foarte simplă - prin inițializarea canalului cu un port folosind cuvântul cheie chan:
let reqport = port();
let reqchan = chan(reqport);
La un port pot fi conectate mai multe canale, dar nu invers - un canal nu poate fi conectat la mai multe porturi în același timp.

Statul de tip

Nu am găsit o traducere general acceptată în limba rusă a conceptului „state de tip”, așa că îl voi numi „state de tip”. Esența acestei caracteristici este că, pe lângă verificarea obișnuită de tip adoptată în tastarea statică, sunt posibile verificări contextuale suplimentare în etapa de compilare.
Într-o formă sau alta, stările de tip sunt familiare tuturor programatorilor - conform mesajelor compilatorului, „variabila este utilizată fără inițializare”. Compilatorul detectează locurile în care o variabilă în care nu a fost scrisă niciodată este citită și emite un avertisment. Într-o formă mai generală, această idee arată astfel: fiecare obiect are un set de stări pe care le poate lua. Fiecare stare definește operații valide și invalide pentru acel obiect. Și compilatorul poate verifica dacă o anumită operație asupra unui obiect este permisă într-un anumit loc din program. Este important ca aceste verificări să fie efectuate în momentul compilării.

De exemplu, dacă avem un obiect de tip „fișier”, atunci acesta poate avea starea „închis” și „deschis”. Și o operație de citire dintr-un fișier nu este permisă dacă fișierul este închis. În limbile moderne, este obișnuit ca funcția de citire fie să arunce o excepție, fie să returneze un cod de eroare. Un sistem cu stări de tip ar putea detecta o astfel de eroare în timpul compilării - la fel cum compilatorul determină că o operație de citire pe o variabilă are loc înainte de orice operație de scriere posibilă, ar putea determina că metoda „Citire”, valabilă în starea „deschis fișierul” , este apelat înainte de metoda „Open”, care transferă obiectul în această stare.

Rust are conceptul de „predicate” - funcții speciale care nu au efecte secundare și returnează un tip bool. Astfel de funcții pot fi folosite de compilator pentru a fi apelate în etapa de compilare în scopul verificărilor statice ale anumitor condiții.

Constrângerile sunt verificări speciale care pot fi efectuate în timpul compilării. Cuvântul cheie check este folosit pentru aceasta.
fn pur este_mai puțin_decât(int a, int b) -< bool { ret a < b; } fn test() { let x: int = 10; let y: int = 20; check is_less_than(x,y); }
Predicatele pot fi „atârnate” de parametrii de intrare ai funcțiilor în acest fel:
fn test(int x, int y): este_mai mic decât(x,y) ( ... )

Există foarte puține informații despre tipstate, așa că multe aspecte sunt încă neclare, dar conceptul este oricum interesant.

Asta e tot. Este foarte posibil să fi ratat totuși câteva puncte interesante, dar articolul era deja umflat. Dacă doriți, puteți acum să construiți un compilator Rust și să încercați să vă jucați cu diverse exemple. Informațiile de asamblare sunt furnizate la


Ne-a plăcut foarte mult articolul „Critica limbajului Rust și de ce C/C++ nu va muri niciodată”. I-am sugerat autorului să traducem articolul în engleză și să îl publicăm și pe blogul nostru. El a fost de acord și suntem încântați să prezentăm acest articol în rusă și engleză. Articolul original este localizat.

Articolul original este postat (text în rusă). Articolul a fost publicat pe blogul nostru cu acordul autorului.

Notă: În cele ce urmează, presupun că Rust este o încercare de a crea un limbaj rapid și sigur. La urma urmei, băieții Mozilla au făcut-o ca instrument de dezvoltare a motorului de browser. Dacă acesta este doar un alt limbaj sigur, atunci obținem ceva ciudat. Există deja un ban într-o duzină de limbi sigure diferite, fiecare va găsi ceva pe placul său. Și dacă scopul nu este înlocuirea C++, atunci (1) de ce este creat un subset nesigur în limbaj? (2) de ce a fost necesar să se elimine fluxurile ușoare din limbă? Nu este convenabil? Cu alte cuvinte, în acest caz, ceea ce se întâmplă nu are deloc sens.

Dacă se întâmplă să citești forumul linux.org.ru, voi reține că aceasta nu este lista de 10 motive pur tehnice pentru a nu-i place Rust despre care a fost discutată în acest thread. După cum arată o discuție pe Skype cu dragă tovarășă @sum3rman, există mai multe opinii cu privire la cât de „tehnic” ar trebui luate în considerare aceste motive. În general, am făcut o listă proastă, dar probabil că voi risca totuși să citez unele dintre cele mai interesante puncte din ea. De fapt, aici există o mulțime de motive simple, non-tehnice.

Faptul că C/C++ nu va merge nicăieri în viitorul apropiat este clar pentru orice persoană treaz. Nimeni nu va rescrie aproape toate aplicațiile desktop, nucleele sistemului de operare, compilatoarele, motoarele de jocuri și browser, mașinile virtuale, bazele de date, arhivele, codecurile audio și video, tone de alte biblioteci bazate pe C și așa mai departe. Acesta este mult, foarte mult cod rapid, depanat, testat în timp. Rescrierea lui este foarte, foarte costisitoare, riscantă și, să fiu sincer, are sens doar în conștiința distorsionată a celor mai încăpățânați fani Rust.Cererea de programatori C/C++ a fost și va fi mare de foarte mult timp.

Bine, ce zici de folosirea Rust atunci când scrii cod nou?

Să ne amintim că aceasta nu este prima încercare de a face un C/C++ „mai corect”. Să luăm, de exemplu, limba D. A apărut în 2001, o limbă foarte bună. Nu există posturi vacante, nici instrumente de dezvoltare normale, nici povești de succes deosebit de remarcabile. Proiectul OpenMW a fost scris inițial în D, iar apoi brusc au decis să-l rescrie în întregime în C++. După cum recunosc dezvoltatorii, au primit multe scrisori în stilul „proiect grozav, am fi bucuroși să contribuim la el, dar nu știm și nu vrem să cunoaștem acest D prost”. Wikipedia raportează că, pe lângă D, au existat o mulțime de alte încercări de a ucide C++ într-o măsură sau alta, de exemplu, Vala, Cyclone, Limbo, BitC. Câți oameni au auzit de asemenea limbi?

Cred că este timpul să învățăm din istorie. Nicio persoană sănătoasă nu va trage o nouă limbă într-un proiect până când măcar nu-i arăți instrumente de dezvoltare normale, nu-i spuneți câteva povești de succes și îi arătați o duzină de programatori în această limbă care locuiesc în apropiere. Programatorii, poate, cu excepția celor mai tineri, nu își vor pierde niciodată timpul și sănătatea în a învăța următoarea limbă cea mai corectă până nu le arătați instrumente de dezvoltare normale (nu artizanat precum Racer), câteva zeci de mii de biblioteci gata făcute ( nu „experimental”, „instabil” și așa mai departe), nu spune câteva povești de succes și nu arăta o duzină de posturi libere în orașul lor. Problema cu puiul și ouăle. Foarte rar, această problemă poate fi rezolvată cu succes (condiționat, Scala poate fi citată ca exemplu), în principal datorită investiției de timp și bani din partea unei companii mari (Google, Typesafe), din anumite motive interesate de popularizarea limba.

După cum am menționat deja, motivele non-tehnice sunt mai mult decât suficiente. Totuși, din pur curiozitate, să încercăm să ne imaginăm pentru o secundă că nu sunt acolo. Atunci nu există niciun motiv să nu scrieți în Rust? Se pare că aceasta este, de asemenea, cel puțin o întrebare foarte mare.

C/C++ este criticat pentru diverse lucruri. Apropo, criticile sunt foarte des făcute de cei care nici măcar de la distanță nu au văzut codul C++ în producție. Problema poate fi descrisă pe scurt și clar după cum urmează: C++ este foarte rapid (și, de asemenea, nu solicită memorie, încărcarea bateriei etc.), dar nu este sigur în sensul că vă permite să depășiți granițele matricelor, să accesați greșit a eliberat bucăți de memorie și așa mai departe. La un moment dat, această problemă a dus la apariția unei mase de limbaje sigure, cum ar fi Java, C#, Python și altele. Dar s-a dovedit că aceste limbaje, în comparație cu C++, sunt prea solicitante de resurse și au alte dezavantaje, de exemplu, inevitabila oprire a lumii în timpul colectării gunoiului. Prin urmare, oamenii se luptă cu sarcina de a face un limbaj la fel de rapid ca C++, dar și sigur. Un astfel de limbaj este Rust.

Rugina este într-adevăr sigură, dar, din păcate, este departe de a fi rapidă. La momentul scrierii, Rust este comparabil ca viteză cu Java, Go și Haskell:

Sper din tot sufletul că în timp va fi cumva overclockat, dar până atunci, din punct de vedere al vitezei și compromisurilor de securitate, nu este cu mult mai interesant decât Scala sau Go. Întrebarea rămâne deschisă dacă este posibil să facem un limbaj rapid și sigur, sau dacă verificările constante pentru depășirea limitelor matricei, legăturile sigure în jurul legăturilor la bibliotecile C și așa mai departe fac automat orice limbă de 2 ori mai lent decât C/ C++.

Ce anume face ca Rust să fie sigur? În termeni simpli, este un limbaj cu un analizor de cod static încorporat. Un analizor static cu adevărat foarte tare care prinde toate erorile tipice C++, nu numai cele legate de gestionarea memoriei, ci și de multithreading. Am transmis un link către un obiect mutabil către un alt fir printr-un canal și apoi am încercat să folosesc acest link eu însumi - nu s-a compilat. E foarte tare.

Se argumentează adesea că doar 10% din cod este executat 90% din timp (ceea ce, din câte am înțeles, este doar o regulă generală - nu am putut găsi rapid nicio cercetare riguroasă pe această temă). Prin urmare, cea mai mare parte a programului poate fi scrisă în Rust sigur, cu 10% din codul fierbinte scris în subsetul nesigur, iar încetineala implementării actuale a Rust nu este cu adevărat o problemă. Ok, dar apoi se dovedește că Rust nu este deloc necesar, pentru că pot scrie 90% din cod în Go și 10% în C. Doar cei care caută glonțuri de argint și teoreticienii necontact vor folosi Rust numai pentru motivul că 100% din program poate fi scris într-o singură limbă. Deși, în realitate, acestea sunt două dialecte ale aceleiași limbi, ceea ce nu este atât de diferit de combinația Java plus C sau Go plus C.

De fapt, regula 10:90 este încă o minciună. Prin această logică, puteți rescrie 90% din WebKit, 90% din VirtualBox sau 90% din GCC în Java și să obțineți același rezultat. Evident că nu este cazul. Chiar dacă ideea nu este că într-un număr de programe această atitudine este foarte diferită, atunci ai grijă la mâini. Să presupunem că întregul program este scris în C/C++ nesigur și timpul său de execuție, relativ vorbind, este egal cu 0,9*1 (o mică parte din cod cald) + 0,1*1 (mult cod rece) = 1. Acum haideți comparați-l cu un program într-un limbaj sigur cu inserții în Si: 0,9*1 + 0,1*2 = 1,1, aproximativ 10% din diferență. Este mult sau puțin? Depinde de scara ta. În cazul Google, chiar și câteva procente pot economisi milioane de dolari (vezi punctul 5 din lucrare, „Utilizare”). Sau imaginați-vă că, odată cu următoarea actualizare, JVM-ul începe brusc să necesite cu 10% mai multe resurse! Mi-e teamă să ghicesc chiar câte zerouri vor fi în cifra obținută după conversia dobânzii în bani americani! 10% este mult în sarcinile în care sunt folosite C și C++.

Repetăm ​​„optimizarea prematură este rădăcina tuturor relelor” ca o mantră. Dar dacă o luăm la propriu, să folosim sortarea cu bule în loc de sortarea rapidă peste tot. Nu știm sigur că programul va încetini în acest loc anume! Ce rost are să împachetezi contoare obișnuite ale unor acțiuni în actori sau în memoria tranzacțională dacă poți folosi imediat atomul mai eficient? Și, în general, în cazuri banale nu are rost să inițializați forțat toate, toate, toate variabilele, să faceți o grămadă de verificări suplimentare și așa mai departe. Să ajungem cu o accelerație nu de 10%, ci de 2-5%. Nici acest lucru nu este rău deloc, dacă a necesitat doar câteva minute suplimentare de gândire. Și așa cum am aflat deja, în problemele rezolvate în C/C++, aceasta poate fi o mare diferență! Apoi, cine a spus că este mai ușor să găsești un punct fierbinte, să rescrieți codul (eventual mult cod) și să demonstrați că este cu adevărat mai rapid decât să vă gândiți la performanță în avans?

Dacă ignorăm problema compromisului viteză-securitate, am și întrebări despre designul limbajului în sine. În special, în ceea ce privește cele cinci tipuri de indicatoare. Pe de o parte, acest lucru nu este rău atunci când programatorul se gândește la locul în care se află variabilele, pe stivă sau în heap și dacă mai multe fire de execuție pot sau nu funcționa cu ele simultan. Dar, pe de altă parte, imaginați-vă că scrieți un program și se dovedește că variabila ar trebui să trăiască nu în stivă, ci în heap. Rescrii totul pentru a folosi Box. Deci înțelegeți că ceea ce aveți nevoie cu adevărat este Rc sau Arc. Rescrii din nou. Și apoi îl rescrieți din nou într-o variabilă obișnuită din stivă. Toate acestea - fără un IDE normal la îndemână. Și jocurile obișnuite nu vor ajuta. Ei bine, sau doar în stilul „Vec” >>>", salut, Java! Dar cel mai trist lucru este că compilatorul știe deja despre durata de viață a tuturor variabilelor, ar putea scoate toate aceste Box, Arc și așa mai departe automat. Dar din anumite motive, această parte a lucrării este transferată pentru programator.Mult mai convenabil ar fi ușor să scrieți val (în mileniul al treilea!), iar acolo unde este necesar, să indicați în mod explicit Box sau Rc. Dezvoltatorii Rust în acest sens au stricat întreaga idee.

Din această cauză, în special, domeniul de aplicare al Rust este foarte restrâns. Nimeni în minte nu ar scrie web și server într-o astfel de limbă. Mai ales având în vedere că nu oferă avantaje semnificative față de aceleași limbi sub JVM. Și Go with normal lightweight threads (nu futurs) arată mult mai atractiv pentru aceste sarcini. Cu futurs, pentru a nu te împușca în picior, mai trebuie să înveți cum să lucrezi și spui „limbaj sigur”. Da, aceste limbi au propriile lor caracteristici, iau aceeași oprire în lume, dar această problemă poate fi rezolvată atât prin tăierea în microservicii, cât și prin alte tehnici. Și da, nimeni nu va traduce Rust în JavaScript, nu va scrie scripturi în el pentru aspect în AWS sau nu îl va folosi ca limbaj de interogare pentru MongoDB. De asemenea, este puțin probabil să scrie pentru Android, dar dintr-un motiv diferit - există mult mai mult de o arhitectură și este mult mai ușor cu JVM. Dacă te-ai gândit brusc că Rust este „potrivit pentru toate sarcinile”, trebuie să te dezamăgesc.

Ei bine, la grămadă:

  • Macro-urile sunt o copie de rezervă a verbozității excesive cauzate de lipsa excepțiilor normale. Am scris deja despre problemele metaprogramarii, în special, este puțin probabil să vedem un IDE normal pentru Rust din cauza asta. Și nu sunt sigur, dar se pare că macrocomenzile din Rust nu au nici măcar spații de nume.
  • Oamenii sunt idioți, iar cargo încurajează cu adevărat să trageți pachete direct din depozitele git, ocolind Crates.io. Drept urmare, există o probabilitate mare de a obține aceeași mizerie cu pachetele ca în lumea Erlang cu Rabar-ul său.Apropo, în lumea Go, pare să fie aceeași situație.
  • Ca multe limbi noi, Rust ia calea simplificării. În general, înțeleg de ce nu există o moștenire normală și excepții în ea, dar însuși faptul că cineva decide astfel de lucruri pentru mine lasă un gust neplăcut. C++ nu limitează programatorul în ceea ce privește ce să folosească și ce să nu folosească.
  • Dacă ar fi să mergem pe calea simplificării, atunci ar trebui să aruncăm toate aceste extensii de limbaj. Altfel, se pare, ca în lumea lui Haskell, fiecare programator scrie în dialectul său.
  • Indicatoarele inteligente, dacă există, sunt departe de a fi gratuite și nu duc la timpi previzibili de colectare a gunoiului. Un fir de execuție are brusc onoarea de a elibera o structură de date foarte profundă. În timp ce el se plimbă prin labirintul verigilor moarte, firele care depind de el devin cu răbdare stupide. Aceeași problemă există și în Erlang cu grupurile sale mici, am observat-o și eu de mai multe ori. Pointerii inteligente au, de asemenea, propriile lor probleme, aceeași fragmentare a memoriei și scurgeri. Am uitat vikpointer-ul din structura ciclică, atât. Și asta într-o limbă care pretinde a fi sigură. Dacă doriți un timp GC previzibil, fie studiați comportamentul aplicației dvs. sub încărcare și luați măsuri (amintiți-vă aceleași grupuri de obiecte) dacă ora GC nu vă convine, fie gestionați manual memoria.
  • A văzut cineva o descriere riguroasă a semanticii Rust? Are cel putin un model de memorie? De asemenea, pentru mine un limbaj „sigur” care „demonstrează corectitudinea” programelor, care poate interpreta codul sursă în zece moduri diferite, ha!
  • Nu pot să nu vă amintesc încă o dată că Problema sunt aproape întotdeauna oamenii, nu tehnologia.. Dacă ajungeți cu cod C++ prost sau Java încetinește brusc, nu este pentru că tehnologia este proastă, ci pentru că nu ați învățat cum să o utilizați corect. De asemenea, vei fi nemulțumit de Rust, dar din diferite motive. Nu ar fi mai ușor să înveți să folosești și să iubești instrumentele mai populare?

În general, în următorii 5 ani aș prefera să-mi investesc timpul în învățarea C/C++ decât în ​​Rust. C++ - acesta este un standard industrial. O mare varietate de probleme au fost rezolvate cu succes în această limbă de mai bine de 30 de ani. Și Rust și altele asemenea sunt jucării de neînțeles cu un viitor vag. Au existat conversații despre moartea iminentă a C++ încă din anii 2000, dar scrierea în C/C++ a început nu mai puțin în acest timp. Dimpotrivă. Și vedem că limbajul se dezvoltă (C++11, C++14), apar noi instrumente pentru el (să ne amintim CLion și Clang) și pur și simplu există o mulțime de posturi vacante corespunzătoare.

Un programator C++ își poate găsi întotdeauna cu ușurință un loc de muncă cu un salariu mai mult decât decent și, dacă este necesar, se poate recalifica rapid în Rust. Opusul este foarte, foarte îndoielnic. Apropo, limba, dacă este ceva, este departe de a fi singurul și nu factorul decisiv în alegerea unui nou loc de muncă. În plus, un programator C/C++ cu experiență poate săpa cu ușurință în codul sursă PostgreSQL sau kernel-ul Linux, să folosească instrumente moderne de dezvoltare puternice și, de asemenea, să aibă la dispoziție o mulțime de cărți și articole (de exemplu, pe OpenGL).

Ai grijă de timpul tău și de sănătate, nu ai atât de mult pe cât crezi!



Bună ziua, dragi cititori!

Viața nu stă pe loc, iar O"Reilly s-a gândit să publice prima carte fundamentală despre limbajul de programare Rust:

Devenind interesați de acest subiect, am decis să aducem în discuție traducerea unui articol de recenzie despre limba Rust, publicat în decembrie 2014. Articolul a fost ușor scurtat din cauza faptului că unele dintre pasajele sale sunt deja depășite, dar autorul aruncă o privire atentă asupra acestui limbaj în contextul alternativelor existente, subliniind avantajele (necondiționate) și dezavantajele (condiționale).

Cu toate acestea, pentru a-l face și mai interesant, să lăsăm în comentariile acestui articol un link către un alt articol despre Rust, publicat pe unul dintre blogurile noastre preferate de programare în limba rusă. Pentru început, mergi la pisica.

Disclaimer: Gustul pentru limbaje de programare este o chestiune foarte subiectivă, la fel ca această postare. Luați-o cu scepticism sănătos.

Mai multe limbaje noi de programare au apărut recent. Printre ei, m-a interesat mai ales Rust. Mai jos voi împărtăși impresiile mele despre Rust și îl voi compara cu alte câteva limbaje de programare.

Barieră în calea învățării Rust

Nu l-am cunoscut pe Rust la prima încercare. Există mai multe bariere în învățarea acestei limbi, inclusiv:

  1. Limba se schimbă rapid. Nu există un „dictator benign pe viață” în Rust. Limbajul evoluează prin contribuțiile membrilor echipei de bază și ale comunității.
  2. Având în vedere primul punct, Tutorialele Rust sunt foarte rare. Există un manual, altă documentație oficială, iar site-ul Rust by Example sunt resurse excelente. Cu toate acestea, Rust este mult mai complex. Adesea trebuie să cercetezi RFC-uri, bloguri și chiar comentarii pe Github pentru a găsi informațiile de care ai nevoie și, chiar dacă aceste informații au apărut chiar ieri, încă nu ești complet sigur de asta. Aștept cu nerăbdare o carte bună, cu autoritate despre Rust, deși pun pariu că va fi lungă.
  3. Sistemul de proprietate al lui Rust și mecanismul de verificare a împrumuturilor pot fi confuze pentru începători. Pentru a asigura siguranța memoriei fără colectarea gunoiului, Rust folosește un sistem complex de împrumut și proprietate. Adesea îi sperie pe neofiți.
  4. Compilatorul Rust este foarte strict. Eu numesc Rust un limbaj de disciplină. Orice lucru care nu este complet evident pentru compilatorul Rust trebuie specificat chiar dvs., iar unele dintre intențiile dvs. s-ar putea să nu fiți conștient la început. Această barieră de învățare, împreună cu toate celelalte, duce adesea la o primă impresie descurajatoare despre Rust.

Avantaje

Rugina are multe avantaje. Unele dintre ele sunt unice.

Siguranța memoriei fără colectarea gunoiului

Aceasta este poate cea mai importantă realizare a lui Rust. În limbajele de programare de nivel scăzut care permit manipularea directă a memoriei, erorile, cum ar fi folosirea după liberă sau scurgerile de memorie în timpul rulării sunt destul de costisitoare. În C++ modern, capacitatea de a face față unor astfel de lucruri s-a îmbunătățit, dar necesită o disciplină tehnică strictă (a se citi: programatorii continuă să efectueze operațiuni nesigure). În consecință, în opinia mea, în general, C++ nu poate rezolva în mod fundamental și fiabil această problemă.

Este adevărat că programatorii Rust pot scrie cod nesigur într-un bloc nesigur, dar (1) acest lucru se face în mod deliberat și (2) blocurile nesigure pot constitui doar o parte foarte mică din întreaga bază de cod, dar sunt strict controlate.
Colectorul de gunoi este cel mai comun instrument de siguranță al memoriei. Dacă te înțelegi cu GC, atunci ai destul de multe opțiuni. Cu toate acestea, sistemul de proprietate al lui Rust asigură nu numai securitatea memoriei, ci și securitatea datelor și a resurselor (vezi mai jos)

RAII și resurse

RAII (achiziția resurselor este inițializare) este un termen ciudat, dar transmite bine ideea. Pe Wikipedia citim că RAII funcționează cu obiecte alocate pe stivă. Sistemul de proprietate al lui Rust permite ca acest principiu să fie aplicat și obiectelor alocate în heap. Acest lucru face ca eliberarea automată a resurselor - de exemplu, memorie, fișiere, socket-uri - foarte previzibilă și garantată în timpul compilării.
Limbajele dinamice precum Python sau Ruby au capacități similare, dar nu se potrivesc cu puterea Rust IMO.

Competitivitate fără curse de date

Rust asigură securitatea datelor în timpul programării concurente - adică asigură că doar mulți cititori sau un „scriitor” pot accesa datele la un moment dat.

Tip de date algebrice

Pe lângă tipurile obișnuite (tupluri și structuri), Rust oferă și tipuri de enumerare (numite aici „tipuri de sumă” sau „tipuri de variante”) și potrivire de modele. Este surprinzător că un limbaj de programare a sistemelor are un astfel de sistem de tip dezvoltat.

Compoziția față de moștenire

Rugina favorizează în mod clar compoziția tipului în detrimentul moștenirii. Sunt în tabăra în care acest fapt este considerat un câștig. Când Rust acceptă tipurile generice, trăsăturile joacă un rol cheie.

Dezavantaje (conditionat)

Totul trebuie să fie foarte clar

Rust este un limbaj disciplinat. Compilatorul trebuie să comunice totul foarte clar, sau va jura până când nu vor mai rămâne puncte neclare. Acest lucru avantajează, în general, calitatea codului, dar poate fi exagerat atunci când vine vorba de prototipuri rapide sau sarcini unice.

Ca rezultat: trebuie să scrieți cod mai bun și mai clar în Rust. Odată ce înțelegi acest lucru, marginile aspre pot dispărea mai mult sau mai puțin.

Colectarea gunoiului este secundară

Rust are un colector de gunoi foarte simplu: Rc, o numărătoare de referință și Arc, o numărare de referință atomică fără detecție round robin. Cu toate acestea, aceste caracteristici nu funcționează în limbă în mod implicit și va trebui să utilizați mai des mecanismele standard de gestionare a memoriei Rust (Stack, & și Box). Dacă problemele de memorie din aplicația dvs. nu sunt semnificative, atunci va trebui să tolerați modelul de siguranță al memoriei Rust, care nu utilizează colectarea gunoiului.

Expresivitatea nu este un scop în sine

Limbajul Rust nu își face griji cu privire la expresivitate sau frumusețea codului. Cu siguranță nu este rău în această privință, dar nu este atât de minunat pe cât ai vrea să fie.

Bariera relativ mare la intrare

În principiu, Rust nu este una dintre acele limbi pe care le puteți stăpâni rapid și scrie cod profesional în câteva săptămâni. Rust este poate mai compact decât C++, dar este cu siguranță mai mare decât multe limbaje de programare. În comparație cu alte limbi, nu poate fi numit foarte accesibil. Aceasta poate fi o problemă dacă prioritatea dvs. este viteza de achiziție a limbii.

Rust și alte limbi

Limbaje dinamice

Limbajele dinamice (de scriptare) se află la capătul opus al spectrului limbajului de programare față de Rust. În comparație cu Rust, scrierea codului în limbaje dinamice este de obicei mai rapidă și mai ușoară. Cred că limbajele dinamice îl înving pe Rust în aceste situații:

  • Prototipări rapide sau sarcini unice
  • Codul nu este pentru producție sau unul în care o eroare la timpul de execuție este o mică problemă
  • Proiect propriu (individual).
  • Lucru semi-automat (de exemplu, analiza/analiza jurnalelor, procesarea loturilor de text)

În astfel de cazuri, nu ar trebui să încercați să faceți totul perfect. Dimpotrivă, Rust, în opinia mea, este mai potrivită pentru:

  • Lucrați într-o echipă medie sau mare
  • Cod orientat pentru utilizare pe termen lung în producție
  • Codul care va fi utilizat pentru o perioadă lungă de timp necesită întreținere regulată și/sau refactorizare
  • Cod pe care ați scrie o mulțime de teste unitare pentru a asigura siguranța

În general, când calitatea codului este critică. Limbajele dinamice vă ajută să scrieți codul mai rapid în stadiul inițial, dar mai târziu munca încetinește: trebuie să scrieți mai multe teste, linia de dezvoltare este întreruptă sau chiar apar întreruperi în producție. Compilatorul Rust te obligă să faci multe lucruri corect în timpul compilării, când este mai puțin costisitor să identifici și să remediezi erorile.

Merge

Compararea acestor două limbi este un motiv excelent pentru a argumenta, dar din moment ce studiez de ceva timp, încă voi împărtăși aici impresiile mele subiective despre aceasta. În comparație cu Rust, iată ce îmi place la Go:

  • ușor - limbajul este mic (și simplu, dar foarte puternic)
  • utilitar gofmt – reduce semnificativ sarcina mentală la programare
  • goroutine/canal
  • Compilare instantanee

De ce am renunțat la Go:

  • E prea minimalist. Sistemul de tipuri și limbajul în sine nu sunt foarte extensibile
  • Programarea Go mi se pare cam uscată. Îmi amintește de zilele în care programam în Java: bun pentru dezvoltarea întreprinderii, mecanic și... nu atât de interesant (reamintire: nu există nicio dispută în privința gusturilor)
  • Popularitatea lui Go continuă datorită suportului Google, dar asta mă face puțin sceptic. Atunci când interesele comunității și ale companiei nu coincid, primul poate fi sacrificat. Desigur, orice companie își urmărește în primul rând propriile interese. Nu este nimic gresit. E doar... puțin enervant. (Multe limbi și cadre promovate de corporații se confruntă cu o problemă similară. Cel puțin Mozilla nu depinde de prețurile acțiunilor.)

Nim

Nim (numit anterior Nimrod) este o limbă foarte interesantă. Compilează în C, deci performanța este destul de bună. În exterior, seamănă cu Python, un limbaj în care mi-a plăcut întotdeauna programarea. Este un limbaj de colectare a gunoiului, dar oferă suport soft în timp real, iar comportamentul colectorului de gunoi în sine este mai previzibil. Are un sistem de efecte interesant. În principiu, îmi place foarte mult acest limbaj.

Cea mai mare problemă în cazul lui este imaturitatea ecosistemului. Limbajul în sine este bine construit și relativ stabil, dar în prezent acest lucru nu este suficient de aproape pentru ca un limbaj de programare să reușească. Documentație, biblioteci standard, depozite de pachete, cadre de suport, participarea comunității și a terților... pregătirea totul pentru producție nu este ușor.

Fără specialiști care să finalizeze limba la timp, această ultimă etapă poate fi foarte istovitoare. Printre noile limbaje de programare, Nim nu se poate lăuda încă cu un suport serios.
Acestea fiind spuse, îi urez succes și să-l urmăresc în continuare.

Alții

Există și alte limbi precum Julia și . Julia este un limbaj dinamic, cu performanțe bune și apeluri fluide în stil C. (Dacă vă plac limbajele dinamice și REPL-urile, acordați atenție). Julia a atras atenția tuturor datorită domeniilor sale numerice și științifice. Deși are potențialul de a deveni o limbă de uz general, mi se pare că dezvoltarea unei limbi este foarte influențată de comunitatea inițiatorilor săi.

D, cel puțin inițial, a fost o încercare de a crea „C++, dar mai bine”. Versiunea sa 1.0 a fost lansată în 2007, așa că această limbă nu este atât de nouă. Acesta este un limbaj bun, dar din motive obiective nu a prins încă rădăcini: motivul este împărțirea în Phobos/Tango într-un stadiu incipient și asigurarea siguranței memoriei în primul rând prin colectarea gunoiului și poziționarea inițială ca înlocuitor pentru C++.

De ce cred că șansele lui Rust sunt destul de mari

Există atât de multe limbaje de programare noi care apar în aceste zile. Ce, după părerea mea, îl face pe Rust să iasă în evidență printre ei? Voi da urmatoarele argumente:

Un limbaj real pentru programarea sistemelor

Încorporarea nu este o sarcină ușoară. Poate că poate fi rezolvată literalmente în mai multe limbi, sau chiar doar în două: C și C++. (Acesta poate fi motivul pentru care Skylight l-a ales pe Rust pentru a dezvolta o extensie pentru Ruby, deși era extrem de riscant.) Este remarcabil cât de bine a reușit Rust să elimine overheadul de rulare. Acest lucru deschide o perspectivă unică pentru Rust.

Fără Null

Obiectul/pointerul nul (așa-numitul „bun de miliarde de dolari”) este o sursă comună de erori de rulare. Există doar câteva limbaje de programare care nu au limbaje nule, majoritatea funcționale. Ideea este că a scăpa de null necesită un sistem de tip foarte avansat. În mod obișnuit, tratarea acestui lucru la nivelul sintactic al limbajului necesită un tip de date algebrice și o potrivire a modelelor.

Limbaj de nivel scăzut cu constructe avansate de nivel înalt

Fiind un „limbaj bare metal” până la bază (cel puțin în teorie), Rust oferă, de asemenea, multe caracteristici de nivel relativ înalt, inclusiv tip de date algebrice, potrivire a modelelor, trăsătură, inferență de tip etc.

Comunitate puternică și relevanță practică

Comunitatea Rust este foarte prietenoasă și activă. (Desigur, aceasta este o impresie subiectivă). În plus, Rust a fost folosit în unele proiecte practice serioase - în special, compilatorul Rust, Servo, Skylight etc. încă în stadiul de dezvoltare a limbajului.

Până acum - fără erori majore

Uneori, dezvoltarea unui limbaj sau a unui cadru în cadrul unei companii poate ajunge accidental într-o fundătură. Din fericire, echipa de bază Rust face o treabă grozavă până acum. Ține-o tot așa, Rust!

Rugina pentru dezvoltare web

Dacă Rust este un limbaj de programare a sistemelor, este potrivit pentru dezvoltarea web? Caut si eu un raspuns la aceasta intrebare.

Biblioteci și cadre

În primul rând, unele biblioteci HTTP trebuie să fie pregătite pentru asta. (Acest lucru este descris pe site-ul web „Are we web yet”). Prima bibliotecă rust-http este deja depășită; Potențialul ei succesor Teepee este practic în animație suspendată. Din fericire, Hyper pare un candidat bun. A fost deja acceptat în Servo, un proiect simbiotic al Rust, pe care îl consider o binecuvântare a fi biblioteca HTTP pentru Rust.

Biblioteca standard Rust nu acceptă încă I/O asincron. În acest scop, puteți utiliza biblioteca externă mio, care oferă I/O socket non-blocante. Suportul firului verde a fost eliminat ca parte a simplificării I/O.

Mai multe cadre web pentru Rust sunt dezvoltate în mod activ, inclusiv Iron și nickel.rs. Poate dura timp înainte ca situația cu ei să se calmeze.

Este Rust o limbă pentru web?

Într-o zi bibliotecile și cadrele vor fi gata. Întrebarea este dacă Rust în sine este potrivit pentru dezvoltarea web? Sunt funcțiile de gestionare a memoriei de nivel scăzut și de securitate ale Rust prea complexe?

Cred că până la urmă totul depinde de ceea ce te aștepți de la proiect. Mai sus, când am comparat Rust cu limbaje dinamice în proiecte pe termen scurt, am menționat că, în astfel de cazuri, complexitatea Rust poate fi nejustificată. Dar dacă vă așteptați ca produsul să dureze mult timp - să zicem, șase luni sau mai mult - atunci Rugina ar putea fi o opțiune bună.

Este Rust bun pentru startup-urile web?

Ce zici de startup-uri? Acestea necesită cicluri rapide de prototipare și dezvoltare. Aceasta este o întrebare mai controversată, dar îmi susțin părerea: dacă vă uitați la un proiect pe termen lung, atunci alegerea limbajului de programare potrivit este importantă, iar Rust merită o atenție specială. Din perspectiva afacerii, un limbaj care permite prototiparea rapidă oferă beneficii semnificative, în timp ce refactorizarea și eliminarea blocajelor pot fi întotdeauna lăsate pentru mai târziu. Realitatea inginerească este că costul lucrărilor de refactorizare este de obicei mai mare decât pare și, chiar dacă zdruncinați o mulțime de elemente ale sistemului dvs., codul scris cu mult timp în urmă va rămâne în continuare într-un colț. Pentru multi ani.

Încearcă Rust!

Puteți ajuta și transfera niște fonduri pentru dezvoltarea site-ului



Cele mai bune articole pe această temă