Rust編程語言做了哪些正確的設(shè)計(jì)?

Rust編程語言目前勢頭很猛,受到了幾大互聯(lián)網(wǎng)巨頭的青睞,比如谷歌、微軟、Meta,亞馬遜等,還作為第二語言進(jìn)入了Linux內(nèi)核,國內(nèi)的華為和字節(jié)跳動等公司也有Rust相關(guān)的應(yīng)用。

本人是一個Rust的粉絲,寫過不少的Rust應(yīng)用,這里我總結(jié)一下我認(rèn)為的Rust相比于其他編程語言的更為正確的設(shè)計(jì):

Sum type

Sum type是比較學(xué)術(shù)的說法,常見于函數(shù)式語言,但是sum type并非函數(shù)式語言的專屬,老大哥C語言的union加上tag之后就是sum type(俗稱tagged union),而動態(tài)類型語言的變量的類型其實(shí)就是封裝出來的sum type類型,比如PHP的變量定義:

typedef union _zend_value {
    zend_long         lval;             /* long value */
    double            dval;             /* double value */
    zend_refcounted  *counted;
    zend_string      *str;
    zend_array       *arr;
    zend_object      *obj;
    zend_resource    *res;
    zend_reference   *ref;
    zend_ast_ref     *ast;
    zval             *zv;
    void             *ptr;
    zend_class_entry *ce;
    zend_function    *func;
    struct {
        uint32_t w1;
        uint32_t w2;
    } ww;
} zend_value;

但是為啥某些主流的靜態(tài)類型語言卻缺失了這個概念(比如Java、Go等)?我是沒想明白的,畢竟老大哥C語言都有這個概念了,缺失了sum type會導(dǎo)致某些需要動態(tài)的場景非常的別扭,比如序列化JSON,舉個例子,需要反序列化如下的JSON:

[1, "foo", null]

Java要怎么做?只能序列化到List<Object>,然后靠類型推斷來判斷是Integer還是String還是Object(null)了,這樣就喪失掉靜態(tài)類型的優(yōu)勢了。

而Rust的sum type關(guān)鍵字enum就很好地解決了這個問題,serde_json庫的Value就已經(jīng)完美地定義了JSON的結(jié)構(gòu):

pub enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

沒有null

這是個老生常談的問題,null的發(fā)明者Tony Hoare將null的設(shè)計(jì)稱為十億美元錯誤,意思是null造成的無法計(jì)數(shù)的錯誤、漏洞和系統(tǒng)崩潰可能已經(jīng)造成了十億美元的損失。

而Rust的解決方式是通過sum type,即Option,來強(qiáng)制用戶必須處理null的情況:

pub enum Option<T> {
    None,
    Some(T),
}

在其他一些沒有sum type語言中也有類似的做法,比如dart的null safety符號?,java的Optional(可惜出來得太晚也不是強(qiáng)制性的)。

賦值默認(rèn)是移動語義

這個是我認(rèn)為非常正確的設(shè)計(jì),普遍的編程語言的賦值都是復(fù)制語義,對于像bool、int、指針之類的基本類型,復(fù)制成本低,因此復(fù)制語義對于他們來說比較合適,包括Rust也為基本類型提供了Copy trait來轉(zhuǎn)換成復(fù)制語義。

但是對于大型的復(fù)合體,復(fù)制語義明顯不適合,因此某些語言區(qū)分了值類型和引用類型,成了各種面試題喜歡問到的東西。

而引用類型的本質(zhì)是封裝了指針,賦值的時候其實(shí)是復(fù)制的指針,指針指向的是同一份內(nèi)存,產(chǎn)生了“引用”的效果。

像Go這類存在指針的語言,那是否“引用”則清晰多了,不過依然存在slice和map這類引用類型,來對抗復(fù)制語義帶來的深拷貝造成的影響。

而Rust則更加正確,同一份內(nèi)存在同一時間只能被一個變量所擁有(所有權(quán)的概念),避免了復(fù)制語義帶來的影響,更加精妙的是,因?yàn)樗袡?quán)的概念,因此可以實(shí)現(xiàn)RAII,這是Rust能夠在無gc的情況下管理內(nèi)存的關(guān)鍵。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容