Rozsda | |
---|---|
Nyelvóra | eljárási programozási nyelv , funkcionális programozási nyelv , többparadigmás programozási nyelv , kötelező programozási nyelv , rendszerprogramozási nyelv [d] , ingyenes és nyílt forráskódú szoftver , fordított programozási nyelv és programozási nyelv |
Megjelent | 2006 [1] [5] |
Szerző | Graydon Kórus [d] |
Fejlesztő | Mozilla [1] , Graydon Hore [d] [1] [2] és Rust Foundation [d] [3] |
Fájlkiterjesztés _ | .rs |
Kiadás |
|
Befolyásolt | Alef [d] [6],C++[7],C#[7],Cyclone[7],Erlang[7],Haskell[7],Limbo[7], Newsqueak [d] ,OCaml[7],Ruby[ 7],Scheme[7],SML[7]ésSwift[7] |
Engedély | Apache License 2.0 [8] [9] és MIT License [8] [9] |
Weboldal | rust-lang.org _ |
OS | platformközi |
Médiafájlok a Wikimedia Commons oldalon |
A Rust (Rust, [ rʌst ]; rust az angolból - "rust") egy általános célú , több paradigmával összeállított programozási nyelv , amely a funkcionális és procedurális programozási paradigmákat egyesíti a tulajdonságokon alapuló objektumrendszerrel . A memóriakezelés a "tulajdonlás" mechanizmusán keresztül történik affin típusok [10] használatával, amely lehetővé teszi, hogy a program végrehajtása során a szemétgyűjtő rendszer nélkül működjön. A Rust garantálja a memória biztonságát a fordító beépített statikus referencia -ellenőrzőjével ( kölcsönellenőrző ). Vannak olyan eszközök, amelyek lehetővé teszik az objektum-orientált programozás technikáinak használatát [11] .
Főbb nyelvi prioritások: Biztonság, sebesség és párhuzamosság . A Rust alkalmas rendszerprogramozásra , különösen ígéretes nyelvnek tartják az operációs rendszermagok fejlesztéséhez [10] . A Rust sebességét és szolgáltatásait tekintve a C++ / C - hez hasonlítható , de nagyobb biztonságot nyújt a memóriával való munka során, amit a nyelvbe épített referenciavezérlő mechanizmusok biztosítanak. A Rust programok teljesítményét a "zéró költségű absztrakciók" [12] alkalmazása segíti elő .
Több éves aktív fejlesztés után 2015. május 15-én megjelent az első stabil verzió (1.0), ezt követően 6 hetente jelennek meg az új verziók [13] . Az 1.0 után kiadott nyelvi verziók esetében a visszamenőleges kompatibilitás deklarálva van [14] .
A 2010-es évek óta fejleszti a Mozilla Research , és a Mozilla Foundation finanszírozza . A tervek szerint 2020-tól kezdődően a szellemi tulajdont, valamint a nyelv fejlesztési és finanszírozási folyamatait átadják a Rust Alapítványnak [15] . 2021. február 8-án az öt alapító cég ( AWS , Huawei , Google , Microsoft és Mozilla ) hivatalosan bejelentette a Rust Foundation megalakulását. [16] [17]
2016 és 2022 között hét egymást követő évben a Rust az 1. helyen áll a "Legkedveltebb programozási nyelvek" listáján az éves Stack Overflow Developer Survey [18] [19] [20] [21] szerint .
A nyelv kidolgozását a Mozilla alkalmazottja, Graydon Hor kezdte 2006-ban. A szerző a projektet Rust-nak nevezte el, szerinte a rozsdacsaládba tartozó gombákkal ( eng . rust fungi ) [22] társítva .
2009-ben [23] a Mozilla külön szponzorálni kezdte a Rust fejlesztését. Egy évvel később a nyelvet hivatalosan is bemutatták a 2010-es Mozilla Summit rendezvényen [24] . Az eredeti, OCaml -ben implementált fordítót lecseréltük egy új, Rust nyelven írt és LLVM -et használó gépi kód generálására [25] ; a következő évben az új fordítóprogram először sikeresen lefordította magát [26] .
A Rust első hivatalos alfa verziója (0.1) 2012 januárjában jelent meg [27] .
2013 áprilisában elindult a Servo , a Mozilla kísérleti projektje egy böngészőmotor fejlesztésére Rustban. [28]
A Rust (1.0) első stabil verziója 2015 májusában jelent meg. A programozási felületek és nyelvi jellemzők jelentős átdolgozáson estek át, ami után alapból már csak a teljesen használatra kész funkciók maradnak, melyek megvalósítása a jövőben sem változik. Az összes többi funkció a kísérleti kategóriába kerül, és alapértelmezés szerint kikerül a szállításból [29] .
Erős statikus gépelést alkalmaznak . Az általános programozás támogatott a parametrikus polimorfizmus támogatásával, a helyi változókra (de a függvényparaméterekre nem) automatikus típuskövetkeztetés biztosított.
Egyedi adattípusok támogatása – olyan típusok, amelyeknek pontosan egy példánya van, és nem foglalnak helyet a memóriában, példák:
Implementált üres adattípusok — nem példányosítható típusok; felsorolt típusokként valósul meg, amelyeknek nincs opciója: enum Void {}.
A nyelv összes adattípusa két fő csoportra osztható: egyszerű és szabványos könyvtártípusokra.
Egyszerű típusok (magába a nyelvbe beépített állandó hosszúságú típusok) - numerikus, logikai, karakter, tömb, szelet, karakterlánc szelet, sor, hivatkozás, függvénymutató. Az egyszerű típusok némelyike "gép", azaz közvetlenül a modern processzorokban valósul meg , mint például a numerikus, logikai és karakteres. A szabványos könyvtár által biztosított típusok std(változó hosszúságú): vektor, karakterlánc, hash tábla és hasonlók.
Numerikus típusok:
Logikai ( bool ): true, false.
Karakter ( char ): Unicode karaktert jelentő típus (a belső adatábrázolás u32-ként). Példaértékek: '₽', '\n', '\x7f', '\u{CA0}',
Funkciómutató ( function pointer ) : A függvényobjektumoknak van egy típusa, amelyet az aláírásuk, azaz a paraméterek és a visszatérési érték határozza meg. Példa:let f: fn(i32) -> i32 = plus_one;
Hivatkozás (megosztott kölcsönzés - megosztott kölcsönzés ) &T(megosztott, nem változtatható, nem birtokol egy erőforrást), ahelyett, hogy átvenné az erőforrás tulajdonjogát, kölcsönkéri azt. Azok a nevek, amelyek kölcsönöznek valamit, nem szabadítják fel az erőforrást, ha kikerülnek a hatókörből. Ezenkívül a tulajdonosok nevei kölcsönzött állapotba kerülnek.
Olyan hivatkozás, amely változtatható (változó kölcsönzés ) ( &mut Tnem birtokolja az erőforrást). Lehetővé teszi a kölcsönzött erőforrás módosítását.
Struktúrák ( struct ):
Felsorolás ( enum ): a Rust-ban szereplő felsorolás minden opciója társítható más adatokkal is, ezért a felsorolást címkézett uniónak vagy összegtípusnak is nevezik . A változatok deklarálásának szintaxisa hasonló a szerkezetek deklarálásának szintaxisához: lehetnek adat nélküli változatok, névvel rendelkező adatok és névtelen adatokkal rendelkező változatok:
Állandók :
A választást előnyben kell részesíteni const, mivel gyakran egy konstansnak nincs szüksége konkrét címre a memóriában, és constlehetővé teszi olyan optimalizálás elvégzését, mint a Constant Folding .
A nyelv olyan memóriakezelési modellt valósít meg, amely a biztonságos párhuzamossági mintákra összpontosít, és megakadályozza a helytelen memória-hozzáférést, ami más programozási nyelvek kritikus szegmentációs hibáinak gyakori forrása. Szabályozást biztosít az inicializálatlan és deinicializált változók használatához; lehetetlen a közös állapotokat több feladat között megosztani; A mutatók élettartamának statikus elemzése és a határokon kívüli tömb ellenőrzése biztosított (automatikusan és mindig, de lehetőség van a check in unsafe-blokkok kikapcsolására a metódussal get_unchecked).
Az úgynevezett Move szemantika implementálva van: alapértelmezés szerint a Rust "áthelyez" ( move ) egy mutatót a kupacban lévő objektumra hozzárendeléskor egy új tulajdonosnak, érvénytelenítve a régi változót. Ez nem történik meg, ha a típus megvalósítja a Másolás tulajdonságot, mert a veremben lévő adatok másolásra kerülnek.
let a = "egy objektum a kupacban adatokkal" . to_string (); // a b változónak átadott objektum // az a változó inicializálatlanná válik, legyen b = a ; // hiba! legyen c = a ; // objektum adatok a veremben legyen a = 55 ; // az objektum egy példányát átadjuk a b változónak, legyen b = a ; // c = 55 legyen c = a ;A memóriamodell másik jellemzője a kölcsönzés ( kölcsönzés ) támogatása a kölcsönzött objektum megváltoztatásának lehetőségével ( &mut) és anélkül ( &): Lexikailag és szemantikailag nagyon hasonlít a hivatkozásokhoz, de vannak sajátosságai: az objektum kölcsönzése hasonló a kölcsönzött objektum szemantikájához. " Vagy sok olvasó, vagy egy író " - egy tárgy egyszer kölcsönözhető a tárgy megváltoztatásának lehetőségével, vagy többször is kölcsönözhető anélkül; a kölcsönök újra kölcsönözhetők egy másik hitelfelvevőnek. A szokásos "Vagy sok olvasó, vagy egy író" szemantikától eltérően nem a szálszinkronizálás kontextusában, hanem általánosan érvényes. A kölcsönzések helyességének ellenőrzése a fordításkor történik, és nem generál további végrehajtható kódot ( nulla költségű absztrakciók elve ). A fordítóprogram szabályozza a kölcsönzött objektumok élettartamának arányát is - a kölcsönzések nem élhetnek tovább ( a hatókörön túl ) a kölcsönzött objektumnál. A kölcsönzések bármilyen adattal működnek, függetlenül azok helyétől (verem, helyi vagy megosztott kupac, egyéb speciális helyek). Különbséget kell tenni a független fogalmak között - magának a kölcsönzésnek a változékonysága ( let mut b = &c) és a kölcsönzött tárgy változékonysága ( let b = &mut c).
Box – Intelligens mutató, amely birtokol egy objektumot a kupacban, megsemmisíti az objektumot, és felszabadítja a memóriát, ha kikerül a hatókörből.
A cella ( Cell , RefCell ) a tartalom megváltoztatását valósítja meg, míg maga a cella megváltoztathatatlan.
Referenciaszámláló ( Rc<T>) és atomi referenciával számlált ( Arc<T>) mutatók: Hivatkozásszámláló intelligens mutatók, amelyek tönkreteszik az objektumot, és felszabadítják a memóriát a számláló nullázásakor. Az Arc szálbiztonságot valósít meg a referenciaszámhoz (de nem magához az objektumhoz). Az Rc és az Arc egy megváltoztathatatlan objektumot vezérel, ezért jellemző felhasználásuk Rc<Cell<T>>egyszálú és többszálú programban egyaránt Arc<Mutex<T>>.
Nyers mutatók megváltoztathatatlan ( *const T) és változtatható ( *mut T): Biztonsági garancia nélkül mutatók. Használatuk erősen nem ajánlott.
A kötések alapértelmezés szerint változtathatatlanok, és egy változó megváltoztathatóvá nyilvánításához szükség van a mut kulcsszóra .
Példák:
legyen x = 80 ; // az x tulajdonost a 80-as értékhez kötjük let mut y = 50 ; // módosítható kötés legyen z = & x ; // megváltoztathatatlan hivatkozás a megváltoztathatatlan kötésre, legyen w = & mut y ; // változtathatatlan hivatkozás a változtatható kötésre legyen r = & mut y ; // hiba: nem lehet második hivatkozást létrehozni egy módosítható kötésre * w = 90 // y = 90 * z = 30 // hiba: Kísérlet a módosításra egy megváltoztathatatlan kötésre hivatkozva legyen n = Box :: new ( 42 ); // csomagolás let m = Rc :: new ( 55 ); // referencia számláló let data = Arc :: new ( "test_string" ) // atomszámlálóPh.D. disszertációjában Ralph Jung formálisan bebizonyította a szálbiztonságot és a memóriakezelés biztonságát RustBelt modelljében particionálási logika és ( Coq alapú ) Iris eszköz segítségével [30] .
A nyelv szintaxisa hasonló a C -hez és a C++- hoz ; a nyelv megkülönbözteti a kis- és nagybetűket, a kódblokkokat kapcsos zárójelek korlátozzák; az if , else , while és for vezérlőstruktúrák szabványos nevei ; a megjegyzéseket is C-formátumban írják; a modulneveket két kettőspont választja el ( ::). Az azonosítók latin betűket, számokat és aláhúzásjeleket tartalmazhatnak. A karakterlánc-literálok bármilyen UTF-8 unicode karaktert használhatnak.
Operátorok halmaza Rustban: aritmetika ( * - szorzás, / - osztás, % - az osztás maradékának felvétele, + - összeadás, - - kivonás és egy unáris előtag operátor -a szám előjelének megváltoztatásához), bitenkénti ( >>, <<, &, |és ^), összehasonlítás operátorok ( ==, !=, <, >, <=, >=), logikai ( &&és ||). A Rust a bináris operátort használja a típusok leadásához as. Az implicit típusú öntés a helyzetek nagyon kis halmazában fordul elő [31] .
A Rust támogatja a makrókat , a reguláris kifejezések helyettesítését, amelyek a fordítás előtti fázisban futnak, fejlettebbek és biztonságosabbak, mint a C. A makrók (makrók) felhasználó által definiált, egyszerű szintaxis-kiterjesztések, amelyek egy paranccsal hajthatók végre macro_rules!. A makró attribútum egy felkiáltójel a név végén. Ugyancsak támogatottak az úgynevezett "procedurális" makrók [32] , amelyek képesek tetszőleges kód végrehajtására fordítási időben.
A kulcsszó letegy kötést (helyi változót) határoz meg.
legyen x : i32 = 5 ;Ez a jelölés azt jelenti, hogy " x típuskötés i32(32 bites egész szám) ötös értékkel".
A nyelvben a match konstrukció a C switch konstrukció általánosított és továbbfejlesztett változata, ráadásul a match a legerősebb, legsokoldalúbb, és akár azt is mondhatnánk, hogy a kulcsfontosságú vezérlőelem nem csak a végrehajtás, hanem a végrehajtás folyamatában is. adatszerkezetek a nyelvben. Az illesztési kifejezésekben több minta is illeszthető a szintaxis használatával |, ami logikai ill.
legyen x = 10 ; egyezés x { 1 | 2 => println! ( "egy vagy kettő" ), 3 => println! ( "három" ) 4 ..= 10 => println! ( "4-től tízig" ), // Ez az ág működni fog, mert 10 ebbe a tartományba tartozik. _ => println! ( "bármi, ami nem felel meg a fenti feltételeknek" ), // A "_" bármely értéknek megfelel }Ha összetett adattípusokkal (struktúra, felsorolás, sor, tömb) dolgozik, a sablonon belül részekre elemezheti őket ("destructurize"). A szerkezet bontása:
structPoint { _ x : i32 , y : i32 , } legyen pont = Pont { x : 0 , y : 0 }; mérkőzéspont { _ Pont { x : 0 , y } => println! ( "x nulla, y egyenlő {}" , y ), // mivel "x" egyenlő nullával, ez az ág működni fog. Pont { x , y : 0 } => println! ( "x egyenlő: {}, y nulla" , x ), Pont { x , y } => println! ( "x = {}, y = {}" , x , y ), }Egy enum megsemmisítése:
enum color { Rgb ( i32 , i32 , i32 ), hsv ( i32 , i32 , i32 ), } legyen szín = Szín :: Hsv ( 0 , 0 , 100 ); match color { Szín :: Rgb ( 0 , 0 , 0 ) | Szín :: Hsv ( 0 , 0 , 0 ) => println! ( "fekete" ) Szín :: Rgb ( 255 , 255 , 255 ) | Szín :: Hsv ( 0 , 0 , 100 ) => println! ( "fehér" ), // ez az ág működni fog. Szín :: Rgb ( piros , zöld , kék ) => { println! ( "piros: {}, zöld: {}, kék: {}" , piros , zöld , kék ) } // minden olyan Rgb-érték esetén működik, amely nem felel meg a fenti feltételeknek. Szín :: Hsv ( színárnyalat , telítettség , fényerő ) => println! ( "árnyalat: {}, telítettség: {}, fényerő: {}" , színárnyalat , telítettség , fényerő ), // ugyanaz, de a Hsv. }Tuple destrukció:
legyen ( a , b ) = ( 1 , 2 ); println! ( "{}" , a ); // 1 println! ( "{}" , b ); 2A szintaxis if letlehetővé teszi, hogy egy kevésbé bőbeszédű konstrukcióvá kombinálja if, letmajd feldolgozza az egyetlen mintának megfelelő értékeket, miközben figyelmen kívül hagyja az összes többit. Ez a szintaxis akkor megfelelő, ha csak egy mintát kell egyeztetni.
legyen x = Néhány ( 10 ); if let Some ( érték ) = x { // itt destrukturáljuk az x-et, a változó értéke a 10-es értéket tárolja. // ez az ág fog végrehajtódni, mert az "x" belül tárolja az értéket. println! ( "érték = {}" , érték ); } másik { // az "else" operátor itt a "_" helyettesítőjeként működik az egyezési kifejezésekben. println! ( "x - üres" ); }unsafeA ( angolból nem biztonságos - „ nem biztonságos”) jelzésű blokkokban és függvényekben a fordító csak öt további dolgot tesz lehetővé:
Alacsony szintű absztrakciók létrehozásakor, különösen a Rust szabványkönyvtár fejlesztésekor kell unsafeigénybe vennie; A normál kódot ajánlatos nélkül írni unsafe.
A Rustban az objektumrendszer vonásokon ( traits ) és struktúrákon ( structs ) alapul. A tulajdonságok metódusaláírásokat határoznak meg, amelyeket minden egyes típushoz (leggyakrabban struktúrához) meg kell valósítani, amely a tulajdonságot megvalósítja. Egy tulajdonság a metódusok alapértelmezett megvalósításait is tartalmazhatja. Egy adott struktúra jellemzőinek megvalósítását, valamint a struktúra saját módszereinek megvalósítását a kulcsszó jelöli impl. A nyelv több tucat beépített tulajdonságot tartalmaz, amelyek többsége a kezelő túlterhelésére szolgál , és amelyek közül néhány különleges jelentéssel bír.
A rozsda támogatja a tulajdonság öröklődésének analógiáját – egy tulajdonsághoz szükség lehet egy implementációs típusra más tulajdonságok megvalósításához. A Rustban azonban nincs nyelvi támogatás maguknak a típusoknak, és így a klasszikus OOP -nak az öröklésére. A típus öröklődése helyett az osztályhierarchia analógiáját jellemzők bevezetésével valósítják meg, beleértve az ősstruktúrát egy gyermek struktúrán belül, vagy felsorolásokat vezetnek be a különböző struktúrák általánosítására [33] .
A nyelv támogatja az általános típusokat ( generics ). A funkciókon kívül a Rust összetett adattípusokat, struktúrákat és enumokat is képes általánosítani . A Rust fordító nagyon hatékonyan fordítja le az általános függvényeket azáltal, hogy monomorfizálja azokat (minden általános függvény külön másolatát közvetlenül minden hívási ponton generálja). Így a másolat adaptálható bizonyos típusú argumentumokhoz, és ezért ezekre a típusokra optimalizálható. Ebből a szempontból a Rust általános funkciói teljesítményükben összehasonlíthatók a C++ nyelvi sablonokkal .
A nyelv korábbi verziói támogatták a könnyű szálakat, de ezeket elhagyták, és a natív operációs rendszer - szálak javára váltak. A szálak közötti adatcsere javasolt módszere azonban az üzenetek küldése a megosztott memória használata helyett. A nagy teljesítmény elérése érdekében nem másolással, hanem saját mutatókkal ( Box<T>) lehet adatokat küldeni. Csak egy tulajdonosra garanciát vállalnak.
Az aszinkron műveletek meghatározása és meghívása nyelvi szintaxis szinten támogatott: a kulcsszó asyncegy aszinkron függvényt vagy blokkot határoz meg; egy ilyen függvény normál hívása egy tulajdonsággal rendelkező objektumot ad vissza Future – egy kezelőt egy lusta aszinkron művelethez [34] . A hívás .awaitlehetővé teszi, hogy egy aszinkron művelet várjon, amíg egy másik aszinkron művelet befejeződik. Ugyanakkor az aszinkron műveletek végrehajtási környezetének megvalósítása sem a nyelv magjában, sem a szabványos könyvtárban nem szerepel, hanem harmadik féltől származó könyvtárak biztosítják [35] .
Modulrendszer: egy összeállítási egység ("láda") több modulból is állhat. A modulok hierarchiája általában megegyezik a könyvtárak és projektfájlok hierarchiájával. A modul (általában) egy külön fájl, egyben névtér és az azonosítók láthatóságának szabályozásának egyik eszköze: a modulon belül (és az almodulokban) minden azonosító „látható”, a magasabb modulokban csak nyilvános ( pub) függvények, típusok, tulajdonságok, állandók, részmodulok, struktúrák mezői.
Automatizált tesztelés: a nyelv lehetővé teszi az automatizált egységtesztek (egységtesztek) megvalósítását közvetlenül a tesztelt modulban vagy almodulban. A vizsgálati módszereket a rendszer figyelmen kívül hagyja a fordítás során, és csak a tesztelés során hívja meg őket. Az integrációs tesztek külön ládákként vannak megvalósítva a tests.
Automatizált dokumentáció: A rustdoc eszköz lehetővé teszi HTML-dokumentáció létrehozását közvetlenül a forráskódból. /// Пример документацииA kódban található dokumentációt hármas perjel ( ) vagy dupla perjel felkiáltójel jelöli , a modul dokumentációja esetén - ( //! Пример документации модуля). A Markdown jelölőnyelv támogatott . A futtatható kód (dokumentációs tesztek) beágyazható a dokumentációba. Ez lehetővé teszi többek között a dokumentáció relevanciájának ellenőrzését a projekt módosítása során.
Csomagkezelő rendszer: cargo csomagkezelő (amely a projektek létrehozásának, összeállításának és tesztelésének fő eszköze is) a Cargo manifest fájl segítségével. A toml feloldja a projektfüggőségeket importált ládákat) úgy, hogy letölti azokat a crates.io tárolóból .
Az azonosítókkal szemben támasztott követelmények: a fordító vezérli a változók, típusok, függvények stb. elnevezési konvencióinak megvalósítását ( snake_case , UpperCamelCase , SCREAMING_SNAKE_CASE ), valamint a fel nem használt azonosítókat; a fel nem használt azonosítókat ajánlott aláhúzással kezdeni; vannak bizonyos irányelvek a konstruktorok elnevezésére, a típuskonverziós módszerekre stb. [36]
A Rust memóriakezelési elvei jelentősen eltérnek a teljes memória-hozzáféréssel és a szemétgyűjtő által teljes memóriavezérléssel rendelkező nyelvektől . A Rust memóriamodellje úgy van felépítve, hogy egyrészt lehetőséget ad a fejlesztőnek arra, hogy szabályozza, hova kell kiosztani az adatokat, bevezetve a mutatótípusok szerinti szétválasztást, és a fordítási szakaszban ellenőrzést biztosít a használatuk felett. Másrészt a Rust referenciaszámláló mechanizmusa hajlamos fordítási hibákat dobni olyan esetekben, amikor más nyelvek használata futási hibákat vagy program összeomlását eredményezi.
A nyelv lehetővé teszi, hogy függvényeket és kódblokkokat „nem biztonságosnak” nyilvánítson ( unsafe). Egyes korlátozások nem vonatkoznak az ilyen nem biztonságos kódokra, így alacsonyabb szinten is lehet műveleteket végrehajtani, de a fejlesztőnek teljes mértékben meg kell értenie, hogy mit csinál.
Mozilla projektek | |
---|---|
Böngészők | |
Egyéb projektek | |
Nem fejlődik | |
Infrastruktúra | |
Alkatrészek |
|