“
也許這篇文章可以消除你對 Rust 的諸多誤解。
背景
Rustacean 是對Rust 編程語言[1]的用戶的稱呼。所以,「Rustacean 原則」可以看作是 Rust 官方團(tuán)隊站在 Rust 語言用戶角度上創(chuàng)造 Rust 語言時所參考的原則。
“
Rustacean 是 Rust +? crustacean 的混合詞。crustacean 是指甲殼綱動物,所以 Rust 社區(qū)將螃蟹作為 Rust 語言的吉祥物,稱之為 Ferris,中文叫摩天蟹。值得明確的是,該吉祥物并非 Rust 官方指定的,最初由 Karen 在 rustacean.net[2] 網(wǎng)站公布了 Ferris 的概念藝術(shù)圖。
Rustacean 原則是由 Rust 語言團(tuán)隊 Leader Niko 在 2021 年所發(fā)起的項目[3],這個項目試圖列舉支配 Rust 設(shè)計和社區(qū)運作方式的原則。Niko 說,這些原則并非代表 Rust 官方而發(fā)布,只是他自己的觀點。建立原則的重點在于嘗試更好地發(fā)展原則并且在團(tuán)隊中使用。
雖然這些是實驗性原則,但該原則在 Rust 官方內(nèi)部經(jīng)過一致性的討論和認(rèn)可。從 Niko 今天發(fā)布的最新博客Rust 異步trait Part8[4] 和 談 “Rust 之魂”[5] 中也看得出來,該原則應(yīng)該已經(jīng)在使用了。
“
去年的時候,因為 Niko 這篇 Rust 原則的文章還引發(fā)了社區(qū)的一些爭議。(前)Rust 核心團(tuán)隊成員 Steve Klabnik 認(rèn)為 Niko 這篇原則是以亞馬遜原則為藍(lán)本的,所以暗示亞馬遜在某種程度上對Rust的開發(fā)負(fù)責(zé)。亞馬遜雇傭了多名Rust維護(hù)者和貢獻(xiàn)者,但它只是眾多有員工參與的公司之一。Rust庫團(tuán)隊負(fù)責(zé)人Mara Bos的觀點卻與之相反,她認(rèn)為Steve的觀點“簡直是胡說八道”。事情經(jīng)過一年回頭再看原則的這些內(nèi)容,其實也沒有 Steve Klabnik 說的那么離譜,Rust 原則的內(nèi)容確實對 Rust Project 開發(fā)和貢獻(xiàn)有指導(dǎo)作用,讓大家知道力往哪里使。
今天打算寫這篇文章,和讀者朋友們一起學(xué)習(xí)一下 Rust 語言創(chuàng)造過程背后所遵循的原則,進(jìn)一步理解 Rust 的設(shè)計哲學(xué)。值得說明的是,Rustacean 原則的大部分詳細(xì)內(nèi)容 Niko 并沒有寫完,所以這里有很多細(xì)節(jié)內(nèi)容是由我來補(bǔ)充的。
Rustacean 原則概要
Rustacean 原則主要分為兩部分內(nèi)容:
Rust 語言如何為用戶賦能,代表 Rust 和 用戶的契約
Rust 社區(qū)如何治理才能更貼近 Rustacean ,代表Rust 團(tuán)隊成員和貢獻(xiàn)者之間的一種“契約”。
這份原則總的來說,是為 Rust 的總體目標(biāo)服務(wù)的。Rust 的總體目標(biāo)是:成為一門賦予每個人構(gòu)建可靠且高效軟件能力的語言。
Rust 如何為用戶賦能
這部分原則內(nèi)容包括:
可靠性( Reliable)。如果它編譯,它就可以工作。
高性能( Performant)。既高效執(zhí)行又使用最少內(nèi)存。
支持性( Supportive)。語言、工具和社區(qū)隨時為用戶提供幫助。
生產(chǎn)力( Productive)。讓工作事半功倍。
透明性( Transparent)。讓用戶可以預(yù)測和控制底層細(xì)節(jié)。
多樣性( Versatile)。你可以用 Rust 做任何事。
Niko 所說的 “Rust 之魂”正是指 Rust 團(tuán)隊在這幾個關(guān)鍵原則之間的斗爭——尤其是生產(chǎn)力、多樣性與透明性之間的權(quán)衡。
可靠性
具體而言,可靠性意味著要保證安全的 Rust 代碼可以避免未定義行為。類型安全是可靠性的關(guān)鍵要素。類型安全不是一種口頭建議,而是靠編譯器來管理。但是類型安全會增加語言的復(fù)雜性,讓 Rust 的學(xué)習(xí)變得更加困難。為此,Rust 團(tuán)隊在錯誤信息和文檔上非常努力,以便減輕這種復(fù)雜性帶來的學(xué)習(xí)成本。正是因為這些成本,Rust 團(tuán)隊才對Rust的類型系統(tǒng)試圖實現(xiàn)的東西施加了一些限制。
比如,對某些類型的錯誤條件采用了運行時檢查。并不試圖證明索引在范圍內(nèi),而是檢查像vec[i]這樣的表達(dá)式,以確保i < vec.len()。在編譯時證明 i< vec.len() 會增加類型系統(tǒng)的復(fù)雜性,所以團(tuán)隊選擇不這么做,盡管這樣會損失一些可靠性,但是增加了生產(chǎn)力。
再比如,允許用戶使用 Unsafe 代碼逃離類型系統(tǒng)的復(fù)雜性。比如,Safe Rust 不能表達(dá)雙向鏈表,但可以用 Unsafe Rust 來實現(xiàn)。然而,也希望用戶能夠封裝(安全抽象)他們的 Unsafe 代碼,向整個世界展示一個安全的界面。這與 Unsafe 代碼作者的生產(chǎn)力感覺相悖(考慮如何封裝東西更復(fù)雜),但對世界其他地方的可靠性卻有很大好處。
另一方面,Rust不隱藏錯誤條件,并鼓勵明確列出所有的可能性(或承認(rèn)某些東西被忽略)。比如,Rust 要求用戶提供詳盡的 match 匹配分支,逼迫用戶去考慮所有情況。這樣做有助于提升 Rust 代碼的可靠性,但這是以降低用戶的生產(chǎn)力為代價的。所以,這是一個權(quán)衡。
錯誤處理就是一個很好的權(quán)衡案例。編程語言歷史長久以來,錯誤處理一般是使用異常。異常處理對用戶而言,提升了生產(chǎn)力。但是異常隱藏了控制流,用戶很難進(jìn)行推理,在實踐中充滿了問題,對可靠性極大的不利。而Rust采用了函數(shù)式語言中首創(chuàng)的返回枚舉的方法,讓用戶強(qiáng)制考慮錯誤處理的方式,這有助于可靠性。其后又引入了?操作符,讓用戶更方便地傳播錯誤,是生產(chǎn)力的提升,同時確保錯誤路徑對用戶來說仍然是可見的,不會被完全忽略。
高性能
Rust 借鑒了 C++ 社區(qū)的零成本抽象概念。Cpp 之父 Bjarne 將零成本抽象定義為:“What you don't use, you don't pay for. And further: What you do use, you couldn't hand code any better”。零成本抽象意味著,用戶可以使用語言提供的高級抽象能力編寫代碼,而編譯器則會通過優(yōu)化為開發(fā)者生成高性能的代碼,進(jìn)一步來說,就是將多余無用的代碼優(yōu)化掉,將有用的代碼優(yōu)化得更加高效。
(圖片來自于 2021 年Rust Dublin的輕talk: Zero Cost Abstractions[6])
這份性能測試并非要踩 C#/Java 語言,只是為了突出 Rust 的零成本抽象能力的性能。你可以看到,Rust 提供了非常優(yōu)雅且和Java/C# 等同的高級迭代器抽象,而不會影響代碼的性能。
這也是被很多人誤會的一點,他們認(rèn)為 Rust 宣傳的零成本抽象是百分之百的。但實際上想要保證百分之百零成本抽象是非常困難的,Rust 在這一方面也充滿了權(quán)衡。
Rust 的開發(fā)者認(rèn)為,零成本抽象,不僅僅是追求零成本和最佳性能,還更應(yīng)該著重改善用戶體驗,因為這就是抽象的意義所在。Rust 語言中的達(dá)到這個標(biāo)準(zhǔn)的零成本抽象特性只有少數(shù)的幾個,這些由 withoutboats 在他的博客中[7]列了出來:
Rust 所有權(quán)和借用機(jī)制。在沒有垃圾收集器的情況下保證內(nèi)存和線程安全是 Rust 最初的巨大成功故事。
迭代器和閉包 API。這是另一個經(jīng)典特性。就像上圖中所示的迭代器代碼一樣,你可以優(yōu)雅地使用各種過濾器、map和for循環(huán),優(yōu)化出來的代碼和手寫的高效 C 代碼等價。
Async/Await 和 Future。Futures API 是一個重要的例子。早期的 Futures (指 0.3 版本之前)很好地達(dá)到了“零成本”的標(biāo)準(zhǔn),但是沒有提供足夠好的用戶體驗。后來通過添加 Pin 來支持跨 await 的引用等,才達(dá)到一個用戶體驗良好的零成本抽象。
Unsafe Rust 和 模塊邊界(可見性)。這是 Rust 其他零成本抽象之母,因為這是 Safe Rust 的基礎(chǔ)。
除此之外的其他特性則沒有取得太大的成功,這有些例子:
trait 動態(tài)分發(fā),目前沒有找到成功的解決方案。
泛型的trait限定,對優(yōu)化有一定阻礙,所以才引入了 特化(Specialization)。
NewType 模式,在某些情況下優(yōu)化并不理想(詳細(xì)可參考延伸閱讀reddit相關(guān)內(nèi)容)。
為什么百分百的零成本抽象這么難?因為 Rust 要考慮的因素太多。除了要為用戶提供體驗良好的抽象之外,還要對透明性和多樣性做權(quán)衡,這些都是對編譯器優(yōu)化干擾的因素。
很多人對 Rust 的另一個誤解就是,用 Rust 實現(xiàn)的代碼性能一定很好。但是實踐結(jié)果很有可能打破他們這層認(rèn)知。開發(fā)者在使用 Rust 代碼的時候需要注意考慮以下幾個問題:
你的抽象有多少成本
你的代碼熱點路徑在哪(調(diào)用頻繁的代碼),該如何優(yōu)化
利用好性能基準(zhǔn)測試
因為 Rust 零成本抽象并不保證用戶寫的 Rust 代碼性能最佳。
支持性
Rust 工具致力于為開發(fā)人員提供優(yōu)美、流暢的體驗。一個例子是編譯器如何提供高質(zhì)量的錯誤消息,這些消息不僅試圖指示錯誤,而且還教用戶 Rust 語言是如何工作的,并就如何修復(fù)他們的代碼提供有用的建議。最近 Rust 官方還啟動了診斷信息多語言翻譯計劃,歡迎大家去貢獻(xiàn)。
對于像 cargo 這樣的工具,這體現(xiàn)在精心的 CLI 設(shè)計中,使“簡單的事情變得簡單”。基于 Cargo 的有用的第三方插件變得越來越豐富。
生產(chǎn)力
生產(chǎn)力可能會與可靠性、高性能有沖突,所以這里也存在權(quán)衡。可以參考上面列舉出來的 Rust 零成本抽象成功的幾個特性,比如所有權(quán)機(jī)制。很多人認(rèn)為所有權(quán)機(jī)制影響生產(chǎn)力,是因為這種安全內(nèi)存管理方式比較新穎,接受起來沒有那么快。但是換成 GC 語言,開發(fā)者就沒有這個心智負(fù)擔(dān),生產(chǎn)力自然提升。但熟練使用 Rust 的開發(fā)者則不會受這個影響。
讓 Rust 變得極具生產(chǎn)力的方法是什么?
Rust 致力于跨版本的穩(wěn)定性。這是因為穩(wěn)定性是生產(chǎn)力的關(guān)鍵推動因素:如果沒有跨版本的穩(wěn)定性,用戶將被迫花時間解決構(gòu)建失敗,而不是構(gòu)建用戶想要構(gòu)建的功能。但是這種穩(wěn)定性也會阻礙 Rust 語言開發(fā)者們對語言特性設(shè)計的自由度,所以引入了 Edition 系統(tǒng)讓設(shè)計自由度和語言版本穩(wěn)定性達(dá)到平衡。
可移植性。默認(rèn)情況下,Rust 代碼旨在跨所有主流架構(gòu)移植。
打造繁榮的生態(tài)系統(tǒng)。
透明性
Rust 官方團(tuán)隊非常重視透明性。透明性是 Rust 提供給用戶的底層掌控力,但需要注意并不意味著它能幫用戶自動提升性能。
但透明性暴露的底層控制細(xì)節(jié),讓多樣性和生產(chǎn)力大打折扣。比如 repr屬性,再比如異步函數(shù)中隨處可見的 Box
透明性與多樣性、生產(chǎn)力有所沖突,在設(shè)計語言特性時需要仔細(xì)權(quán)衡。
多樣性
Rust 同樣重視多樣性,多樣性意味著通用性,意味著 Rust 可以做上層的應(yīng)用,也可以做底層的系統(tǒng)開發(fā)。
官方的目標(biāo)是以某種方式向 Rust 程序公開所有核心系統(tǒng)功能,即使訪問或正確使用它們可能很困難。而不希望 Rust 用戶覺得他們必須選擇 C 或其他語言,他們應(yīng)該能夠使用 Unsafe Rust 來完成他們的工作。像“內(nèi)聯(lián)匯編”這樣的功能也遵循這種思路。
我能想到一個比較典型的例子是,Rust 將 Error trait 移動到了 core 中,這樣就可以統(tǒng)一 std 和 no_std 的錯誤處理了。
Rust 社區(qū)如何治理才能更貼近 Rustacean
該部分內(nèi)容提供了以下一些原則,用于幫助 Rust 核心團(tuán)隊和社區(qū)貢獻(xiàn)者良好合作:
善良體貼。相互尊重彼此才是構(gòu)建 Rust 未來的基礎(chǔ)。
給用戶帶來快樂。首要目標(biāo)是讓 Rust 用戶更有效率和能力。希望人們喜歡使用 Rust,如果他們愿意,也喜歡參與它的社區(qū)。
暢所欲言地表達(dá)自己。帶上你的專業(yè)知識,并愿意為你認(rèn)為正確的事情進(jìn)行辯論。
認(rèn)可別人的知識。沒有人能壟斷好的創(chuàng)意。Rust 團(tuán)隊需要汲取優(yōu)秀的建議來改進(jìn)設(shè)計。
從小處開始。尋找完美的設(shè)計需要迭代。大處著眼,小處著手;當(dāng)你了解更多時,不要害怕改變。
跟進(jìn)。說你會做的,做你說的。
把愛傳出去。Rust項目成員需要識別有潛力的貢獻(xiàn)者,有義務(wù)去發(fā)展新的成員,并且當(dāng)好教練的角色。
信任和委托。賦予他人權(quán)力意味著愿意讓他們以他們認(rèn)為最好的方式做出決定。
P.S 金發(fā)姑娘原則
在 Niko 的博客中還提到一個金發(fā)姑娘原則(Goldilocks),比較有趣。
該原則出自一個英國的童話故事《金發(fā)姑娘和三只熊》。
講的是一位金發(fā)姑娘偷偷跑進(jìn)熊的家里,她發(fā)現(xiàn)了三碗粥、三把椅子和三張床,粥有冷的、有熱的;椅子有硬的、有軟的;床有大的、有小的。她都嘗了、都試了以后,選擇了不冷不熱的那碗粥,不硬不軟的那把椅子,不大不小的那張床,因為那碗粥、那把椅子、那張床最適合她,對她來說都是“剛剛好”,這種選擇的原則就叫做“金發(fā)姑娘原則”。
“金發(fā)姑娘原則”被應(yīng)用在各個領(lǐng)域,比如發(fā)展心理學(xué)、經(jīng)濟(jì)學(xué)、通訊科學(xué)、醫(yī)學(xué)和天體生物學(xué)、溝通等等。
如果把該原則用在如何看待(新)事物方面,那么它會成為一個非常好的思維工具。通過該原則,可以讓你避免用非黑即白的思維看待這個世界存在的事物,比如 Rust 語言,比如某個人。這個世界并不是好與壞、黑與白這兩個極端,它還存在中間狀態(tài)。
小結(jié)
本文可能還缺少很多細(xì)節(jié),但總體上我認(rèn)為應(yīng)該把 Rustacean 原則和 Niko 所說的 Rust 之魂講清楚了。Rust 語言并不完美,但它在這些原則之間不斷權(quán)衡而發(fā)展。我們可以不完美,也不可能完美,但不能不追求完美。感謝閱讀。
審核編輯 :李倩
-
編程語言
+關(guān)注
關(guān)注
10文章
1950瀏覽量
34989 -
Rust
+關(guān)注
關(guān)注
1文章
230瀏覽量
6666
原文標(biāo)題:Rustacean 原則 與 Rust 之魂
文章出處:【微信號:Rust語言中文社區(qū),微信公眾號:Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
SHA105概要數(shù)據(jù)手冊
![SHA105<b class='flag-5'>概要</b>數(shù)據(jù)手冊](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
SHA106概要數(shù)據(jù)手冊
![SHA106<b class='flag-5'>概要</b>數(shù)據(jù)手冊](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
ECC206概要數(shù)據(jù)手冊
![ECC206<b class='flag-5'>概要</b>數(shù)據(jù)手冊](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
詳解SMT工藝的五球原則
![詳解SMT工藝的五球<b class='flag-5'>原則</b>](https://file1.elecfans.com//web3/M00/00/F7/wKgZO2dPrCqAE4UnAAD7BicELCc72.jpeg)
PCB上設(shè)置測試點的基本原則
差動保護(hù)動作電流整定原則
放大線路的組成原則是什么
安全型繼電器要符合什么原則
PGA309正常只校準(zhǔn)一個溫度點大概要多久時間呢?
組成放大電路的基本原則是什么?
浪涌保護(hù)器配置原則及行業(yè)應(yīng)用
![浪涌保護(hù)器配置<b class='flag-5'>原則</b>及行業(yè)應(yīng)用](https://file1.elecfans.com/web2/M00/8F/90/wKgaomTQYLuAPXtLAAMJsTut9Wg380.png)
評論