在不背離安全或抽象的情況下,擁有極高的運行效率,能預防幾乎所有的錯誤,提供優越的底層控制和性能——這些都是Rust1.0版本做出的承諾,而這僅僅是個開始。
經過幾年的迭代改進,Rust編程語言日前發布1.0版本。作為一種現代系統語言,Rust從大量語言(如C/C++)中取其精髓,去其糟粕,同時具備底層控制、高性能和強大的並發性。為了做到這一點,Rust打破了許多傳統的取捨,它提供:
沒有垃圾收集
軟件工程中,垃圾回收是一個強大的工具,讓你從手動跟蹤內存的煩惱中解脫,而專注於寫出更好的代碼。雖然有垃圾回收器很不錯的,但是它在一些領域卻不那麼合適,諸如操作系統、嵌入式庫和(軟)實時應用,它們通常需要更大程度的控制和可預測性,而垃圾回收不能提供這些。
Rust允許開發人員完全放棄垃圾收集器,且不會面臨忘記釋放資源、懸掛指針、段錯誤的風險。所有權(ownership)和借用 (borrowing)是Rust實現這些的關鍵概念,這個想法在編程中無處不在,也是現代C++的一個重要組成部分。但與其他語言不同的是,Rust把 他們放在了核心地帶,靜態地檢查和利用它們,來保證沒有垃圾回收器情況下內存的安全,這是之前不能想象的東西。
關於所有權(Ownership),Rust的理念是每一個值只能有一個所有者(parent)對其完全控制。隨著這些值被重新分配、放在數據結 構中或傳遞給函數,它們的所有權會轉移,且不能再通過原來的路徑訪問。如果超出它的作用域(scope),所有權還未被轉移,它就會被自動銷毀。為了使所 有權在一定范圍內運作,Rust提供了一種在值的作用域范圍內臨時借用(指針指向值)的方法。
所有權不僅替代了垃圾回收,對保證並發性也至關重要,甚至避免諸如迭代器失效這類型的bug。Rust還適用於內存以外的其他資源,例如當你關閉套接字或者文件時,可以將你從管理中解放出來。
並發性
如前所述,所有權也保證了你的並發程序不會陷入數據競爭(data races)的隱患之中。所有權會使之保持不牢固的內存模型,通過硬件來接近它。
用Rust開始一個並發程序很簡單,通過標准庫將閉包傳遞給函數:
Java代碼
use std::thread;
fn main() {
let some_string = "from the parent";
thread::spawn(move || {
// run on a new thread
println!("printing a string {}", some_string);
});
}
許多並發程序設計語言的原則之一就是共享狀態應該最小化或者甚至完全禁止,取而代之的是通過消息傳遞,所有權意味著Rust語言中的值默認只有一個所有者,所以通過通道將一個值發送給新的線程時保證原始線程不能訪問它——靜態禁止共享。
然而,消息傳遞僅僅是工具箱中的一個工具,共享內存可能也非常有用。類型系統確保只有線程安全的數據才可以在線程之間進行共享。例如,標准庫提供 了兩種類型的引用計數:Arc提供線程安全的A共享內存(默認不可變),而Rc類型則可以放棄那些需要保證線程安全的同步,在Arc上提供一個性能提升。 這種類型的系統靜態地確保不會不小心從一個線程向另一個線程發送Rc值。
當你想確實想改變內存時,所有權提供了進一步的幫助。標准庫Mutex類型為數據提供了一個類型參量,可以受到鎖的保護。之後所有權確保這個數據只有在持有鎖的時候才能訪問,但你不能刻意提前開鎖。這種訪問控制貫穿了Rust類型系統,並被廣泛的用於它的標准庫。
零成本抽象性能和可預測性是Rust的目標之一,達到這個目標很重要的一步就是不但要保證安全,還要提供比C++更強大的零成本抽象。Rust允許你構建高層次抽象,編譯為特定代碼的范型庫,避免為各種情況編寫代碼。
為了做到這點,Rust精確控制內存布局,數據可以直接放置於堆棧或內聯在其他數據結構之間,而堆分配要比大多數托管語言少,有助於獲得更好的緩存局部性,而這是現代硬件中提升性能到重要因素。
這個簡單的、直接的數據布局意味著優化器可以可靠地消除函數調用和類型的層,將高層代碼編譯為高效和可預測的機器碼。迭代器是其中一個主要的例子,下面的代碼是對一個32位整數序列平方求和的慣用方法:
Java代碼
fn sum_squares(nums: &[i32]) -> i32 {
nums.iter()
.map(|&x| x * x)
.fold(0, |a, b| a + b)
}
在整數切片上一次運算完成,當優化開啟時,甚至編譯為SIMD向量指令。
強大的類型
傳統上,函數式編程語言提供類似代數數據類型、模式匹配、閉包和靈活的類型推斷的功能。Rust是許多新開發的語言之一,它並不是直接適用具有這些特性的函數模型,而是用一種方式合並它們——允許在不損耗性能的情況下適用的一個靈活的應用程序接口(APIs)。
上面的迭代器示例得益於許多這樣的想法:這完全是靜態類型,但類型推斷意味著不必要寫明那些類型。閉包也是至關重要的,它允許簡潔地編寫操作。
在多數主流編程語言中,代數數據類型是枚舉(enums)的一個擴展,它允許一個數據類型由一組離散的選擇組成,且每個選擇都會附加信息:
Java代碼
struct Point {
x: f64,
y: f64
}
enum Shape {
Circle {
center: Point,
radius: f64
},
Rectangle {
top_left: Point,
bottom_right: Point
},
Triangle {
a: Point,
b: Point,
c: Point
}
}
模式匹配是使操縱這些類型變得簡單的關鍵,如果shape是一個Shape類型的值,你可以處理各種可能性:
Java代碼
match shape {
Shape::Circle { radius, .. } => println!("found a circle with radius {}",
radius),
Shape::Rectangle { top_left: tl, bottom_right: br } => {
println!("found a rectangle from ({}, {}) to ({}, {})",
tl.x, tl.y,
br.x, br.y)
}
Shape::Triangle { .. } => println!("found a triangle"),
這些編譯器可以確保你解決所有情況(選擇性加入一個catch-all分句),並極大程度地幫助重構。
枚舉(enums)也使得Rust防治所謂的“價值數十億美元”的錯誤:空引用(null references)。在Rust中引用永遠不會是空的,選擇類型允許你以一種類型安全、本地化的方式選擇nullability。
結論
Rust是一種由Mozilla贊助的語言,它在保留C++性能的同時提供零開銷抽象,用於web浏覽器開發,還能同時保證內存安全和緩解並發編程的壓力。
Rust填充了一個也許被認為是不可能的利基:在不背離安全和抽象的情況下,提供底層控制和性能。當然,世界上沒有免費的午餐,編譯器作為一個要求 助理不能容忍一點點風險,而且所有權模式還有點陌生,需要一些時間學習。
1.0版本的核心語言和庫已經被測試和精煉過,而且重要的是關於穩定的保證:現在編譯的代碼應該也可以在未來的新版本中得到編譯。並且,這個版本 並不意味語言的完成,Rust正在采用火車模型,新版本每六周發布一次,新的和不穩定的特性可以通過常規的預發布版本betas和nightlies發 現。目前,一個標准的包管理器Cargo已經被用來建立一個不斷增長的庫系統。
正如語言一樣,Rust生態還不完善,所以沒有像許多老一輩的語言提供的那樣寬廣的工具和包(簡單的FFI雖然對後者有所幫助)。盡管如此,語言本身是強大的,也是一個沒有傳統危險的,去做底層開發很好的方式。
為什麼我說 Rust 是靠譜的編程語言 http://www.linuxidc.com/Linux/2015-05/117711.htm
Rust 1.2 穩定版發布下載,Mozilla 編程語言 http://www.linuxidc.com/Linux/2015-08/121290.htm
Rust 的詳細介紹:請點這裡
Rust 的下載地址:請點這裡
原文鏈接:Why you should take a closer look at Rust 1.0