Språket Rust, som först skapades av Graydon Hoare och som nu stöttas av Google, Microsoft, Mozilla, Arm och andra, är ett försök att lyckas med detta. Googles språk Go har liknande ambitioner, men Rust är gjort för att göra minsta möjliga eftergifter till prestanda.

Rust är tänkt att vara snabbt, säkert och någotsånär enkelt att programmera i. Det är också tänkt att bli spritt, inte bara en kuriositet eller en av många tävlande i språklotteriet. Det finns goda skäl att konstruera ett språk som lägger lika stor vikt vid säkerhet som vid hastighet och utvecklingskapacitet. Det finns ju faktiskt massor med program – varav en hel del kör vital infrastruktur – som är skrivna i språk som inte sätter säkerheten i första rummet.

Fördelar med programspråket Rust

Rust började som ett forskningsprojekt i Mozilla, bland annat med syftet att återskapa viktiga delar av webbläsaren Firefox. Några av huvudskälen för detta var att Firefox borde kunna fungera bättre på moderna processorer med många kärnor, och eftersom det finns webbläsare överallt behöver de vara säkra för användarna.

Men de fördelarna behövs i all mjukvara, inte bara webbläsare. Därför växte Rust från ett språk för webbläsarkomponenter till ett heltäckande programspråk. Rust har blivit säkert, snabbt och lättanvänt på grund av dessa egenskaper:

Rust är snabbt

Rustkod kompileras till otolkad maskinkod för många plattformar. Binärkoden står på egna ben. Det behövs inga externa program, förutom de som operativsystemet kan ha, och den genererade koden är tänkt att vara lika snabb som jämförbar kod skriven i C eller C++.

Rust är minnessäkert

Rust kompilerar inte program som försöker använda minnet på osäkra sätt. De flesta minnesfel upptäcks när programmen körs. Men Rusts syntax och metaforer gör att sådana minnesproblem som är vanliga i andra språk – tomma eller dinglande pekare, kapplöpningar och annat – aldrig kommer i produktionen. Kompilatorn varnar för sådana fel och tvingar programmeraren att rätta till dem innan programmet kan kompileras och köras.

Rust har låga omkostnader

Rust styr minneshanteringen med stränga regler. Rusts minneshanteringssystem beskrivs i språkets syntax med en metafor som kallas för ägande (ownership). Varje givet värde i språket kan ”ägas”, alltså hållas och manipuleras, av endast en enda variabel åt gången. Varje bit minne i ett Rustprogram hanteras och släpps automatiskt genom ägandemetaforen.

Överföringen av ägande mellan objekt är hårt styrd av kompilatorn, så vid exekveringen blir det inga överraskningar som minnesallokeringsfel. Arbetssättet med ägande gör att Rust inte behöver sophämtning i minneshanteringen, som språk som Go eller C#. Det ger Rust ännu högre prestanda.

Rust är flexibelt

Rust kan låta dig leva farligt om du måste, men bara till en gräns. Spärrarna i Rust går delvis att lyfta om man måste kunna gå direkt in i minnet, till exempel för att avreferera en rå pekare som i C/C++. Nyckelordet här är delvis, för Rusts funktioner för säkert minne går aldrig att stänga av helt. I vilket fall som helst behöver du nästan aldrig kunna ta av säkerhetsbältet, så i slutänden får du mjukvara som är säker som standard.

Rust är enkelt att driftsätta

Inga av Rusts funktioner för säkerhet och integritet är värda något om ingen använder dem. Därför har Rusts utvecklare och anhängare strävat efter att göra språket så användbart och välkomnande som vanligt för noviser.

Allt som behövs för framtagning av binärkod från Rust kommer i samma förpackning. Externa kompilatorer, som GCC, behövs bara om du kompilerar andra komponenter som inte ingår i Rusts ekosystem. (Som ett C-bibliotek som du kompilerar från källkod.) De som använder Microsoft Windows behöver inte känna sig som andra klassens medborgare. Rusts verktyg fungerar lika bra för Windows som med Linux och MacOS.

Rust är plattformsoberoende

Rust fungerar på de tre stora plattformarna: Linux, Windows och Mac OS. Andra plattformar har också stöd. Om du vill korskompilera, alltså ta fram binärkod för en annan arkitektur eller annan plattform än den du kör nu, krävs en del extraarbete, men Rust är gjort för att sådant ska kunna göras med minsta möjliga möda. Och även om Rust fungerar på huvuddelen av alla plattformar så har dess skapare inte strävat efter att göra Rust kompilerbart för allting – bara på de plattformar som är populära, och där man inte behöver göra oönskade kompromisser med språket.

Rust har kraftfulla funktioner

Få utvecklare vill börja med ett nytt språk om de märker att det har färre, eller klenare, funktioner än de som de är vana vid. Rusts funktioner står sig bra mot de som finns i språk som C++. Makron, generiskt, mönstermatchning och komposition (genom ”traits”) är första klassens medborgare i Rust. En del funktioner som finns i andra språk, som inline assembler, finns också, fast markerat som ”osäkert” i Rust.

Rust har ett användbart standardbibliotek

I satsningen på Rust ingår att uppmuntra utvecklare att byta från C och C++ till Rust överallt där det är möjligt. Men C- och C++-programmerare förväntar sig ett hyfsat bra standardbibliotek. De vill kunna använda containers, collections och iterators, kunna utföra strängmanipulationer, hantera processer och trådning, utföra I/O för nätverk och filer, och så vidare. Rust klarar allt det, och mer därtill, i sitt standardbibliotek. Eftersom Rust är utformat för att vara plattformsoberoende kan standardbiblioteket innehålla endast sådant som på ett säkert sätt kan portas mellan plattformarna. Plattformsspecifika funktioner som Linux epoll måste stöttas genom funktioner i tredjepartsbibliotek som libc, mio eller tokio.

Man kan också använda Rust utan standardbiblioteket. Ett skäl att göra så kan vara att få fram binärkod som saknar plattformsberoende, till exempel ett inbyggt system eller en operativsystemskärna.

Rust har många tredjepartsbibliotek, eller ”crates”

Ett mått på ett språks användbarhet är hur mycket det kan uträtta med hjälp av tredje part. Cargo, det officiella kodförrådet för Rustbibliotek (så kallade ”crates”) har över 60 000 crates. En rejäl del av dem är api-kopplingar till vanliga bibliotek eller ramverk, så Rust kan fungera ihop med de ramverken. Dock har Rust-användarna hittills inte sammanställt en detaljerad utvärdering eller rankning av dessa crates, så det går inte att få veta vilka som fungerar bra utan att pröva själv, eller fråga sig fram.

Rust har bra stöd för IDE

Återigen – få utvecklare vill börja använda ett programspråk med lite eller inget stöd för den integrerade utvecklingsmiljö (IDE) som de föredrar. Därför har Rust-teamet utvecklat Rust Language Server som ger direkt återkoppling från Rust-kompilatorn till IDE:er som Microsoft Visual Studio Code.

rust
Direkt återkoppling i Visual Studio Code från Rust Language Server. Rust Language Server har mer än bara grundläggande syntaxkontroll. Det styr också sådant som användning av variabler. (Klicka på bilden för större version.)

Nackdelar med Rustprogrammering

Bortsett från dessa attraktiva, kraftfulla och användbara egenskaper har Rust sina avigsidor. En del av dem sätter krokben både för nya ”rustaceans” (Rust-fantasternas namn på varandra) och veteraner.

Rust är nytt

Rust är fortfarande ett nytt språk. Version 1.0 kom 2015. Så även om språkets centrala delar som syntax och funktion sitter där de ska finns det annat som fortfarande flyter.

Asynkrona operationer är till exempel fortfarande på gång i Rust. En del av async har kommit längre än andra, många komponenter tillhandahålls av tredjepartskomponenter.

Rust är svårt att lära

Om det finns något med Rust som är svårare än annat så är det att det kan vara svårt att begripa sig på Rusts metaforer. Ägande, lånande (borrowing) och Rusts andra påfund i minneshantering sätter krokben för alla i början. Många nybörjare i Rustprogrammering genomlider en initieringsrit, ”fighting the borrow checker”, där de direkt upplever hur petig kompilatorn är när det gäller att hålla isär föränderliga (mutable) och icke föränderliga saker.

Rust är komplext

En del av svårigheterna beror på att Rusts metaforer leder till mer mångordig kod, jämfört med andra språk. Till exempel är strängkonkatenering i Rust inte alltid så enkel som string1+string2. Det ena kan vara mutabelt, det andra inte. Rust brukar vilja att programmeraren tydligt anger hur sådant ska hanteras, inte bara låter kompilatorn gissa.

Ett annat exempel är hur Rust och C/C++ fungerar ihop. Ofta brukar Rust koppla in sig på existerande bibliotek skrivna i C eller C++. Få projekt skrivna i C eller C++ skrivs om från grunden i Rust. (Och om det sker brukar det ske bit för bit.)

Rust är ett systemspråk

Precis som C och C++ kan Rust användas för att skriva mjukvara på systemnivå, eftersom det tillåter direkt manipulering av minnet. Men för en del jobb är det att ta i. Om du har jobb som mest handlar om I/O, eller som inte kräver maskinhastighet kan Rust vara för otympligt. Ett Python-skript som tar fem minuter att skriva och en sekund att köra kan vara ett bättre val för utvecklaren än ett Rustprogram som tar en halvtimme att skriva, men körs på en hundradels sekund.

Färdplan för Rust

Rust-teamet är införstått med många av dessa problem och jobbar på att lösa dem. För att, till exempel, göra det enklare att använda Rust tillsammans med C och C++ undersöker Rust-teamet om det går att bredda projekt som bindgen, som automatiskt genererar Rust-bindningar till C-kod. Teamet jobbar också på att göra borrowing och lifetimes mer flexibla och lättare att förstå.

Hur som helst har Rust lyckats bli ett säkert, integrerat och hanterbart systemspråk på sätt som andra språk inte kan, och det gör det på ett sätt som ansluter till hur utvecklare redan arbetar.