學習 Rust 你需要一個認知框架
前言
如果你學習 Rust 的過程感覺到艱難、痛苦或迷茫,不妨看一下這篇文章。 但如果你學 Rust 感覺很輕鬆,那這篇文章就對你無用,可以忽略。
雖然現在 Rust 學習資料非常豐富,但 Rust 是一門學習成本相對比較高的語言。面對不同語言經驗的人,學習成本略有差別。
在學習 Rust 之前,需要了解你將會在 Rust 學習過程中付出什麼樣的心智成本。
零基礎的人,需要補足一些必要的計算機科學相關的基礎,以及建立對編程的理解。初學編程本身就是一項很大的挑戰。
有一定編程基礎的人,雖然對學習 Rust 有一定幫助,但還是會有一些阻礙。
- 只有 C 經驗的人,學習 Rust 語法時候,有如下挑戰:
-
Rust 編程範式。c 語言是過程式,而 Rust 是混合編程範式,支持面向對象和函數式編程風格。c 語言過來的人,很容易把 Rust 寫成過程式風格,雖然用過程式也可以用 Rust 寫出完整功能,但在代碼架構上會損失 Rust 的優勢。和編程範式相關的概念:泛型 / trait / 錯誤處理 / 結構體 / 枚舉 。
-
所有權和借用檢查。c 裏面是 手動管理內存,但是 Rust 是用所有權來管理。c 裏面都是用指針,但是在 Rust 裏,將指針進行了安全抽象變成了引用,需要有借有檢查。這些都是 c 開發者必須要掌握的概念。
-
Unsafe Rust 安全抽象。c 語言開發者要理解 Unsafe Rust 的編碼規範,理解如何進行安全抽象,這一點比較重要,尤其是和 C 相互調用時。
-
宏。Rust 中聲明宏類似於 C 語言的聲明宏,都是代碼替換,但是功能比 C 的強大,這些應該也算一個學習挑戰。Rust 還有功能更強大的過程宏,可以在前期學習的時候不用考慮,後期再學。
- 有 Cpp 經驗的人,默認其對 C 有一定了解,學習 Rust 語法時,有如下挑戰:
-
Rust 編程範式。Rust 的混合範式 和 Cpp 的混合範式不同。Rust 不是純粹的面嚮對象語言,沒有構造函數。Rust 中的泛型、 trait 、枚舉 和 錯誤處理 對於 Cpp 開發者同樣是重點。
-
所有權和借用檢查。因爲 Rust 也引入了 和 Cpp 11 引入的 基於 RAII 機制的智能指針,所以在內存管理方面,對 Cpp 11 及以上版本有經驗的人更容易理解。但是沒有這方面經驗的 Cpp 開發者就有一定難度了。
-
Unsafe Rust 安全抽象。這一點和 C 語言開發者一樣,是需要對 Unsafe Rust 的編碼規範有一定理解。
-
泛型 和 過程宏。Cpp 開發者有模版,但是 Rust 中有泛型。Rust 中泛型的功能沒有 Cpp 模版強大,但是有過程宏可以彌補。也就是說 Cpp 模版編程 等價於 Rust 的泛型和過程宏的結合。如果 Cpp 開發者也想要在 Rust 中追求 模版編程的效果,那麼需要掌握 泛型和過程宏。
- 只有 GC 語言使用經驗的人,比如 Java、Python、Ruby 、Haskell 等,學習 Rust 語法面臨的挑戰和 Cpp 基本相同,但因爲使用 GC 語言的人,大部分對底層內存管理沒有足夠深入的瞭解,入門曲線會更加陡峭。
所以, Rust 入門曲線陡峭與否,除了語言本身的複雜性之外,也跟每個人的編程基礎有關。
Rust 認知框架介紹
認識到 Rust 學習曲線的根由之後,你會發現,你以往的編程知識其實無法平滑遷移到 Rust 語言的學習中。
所以,你需要一個通用的學習框架,按這個框架來給自己制定學習計劃,來達到對抗這個學習曲線,並達成入門 Rust 並持續學習的目的。
這個學習框架其實很簡單,只需要明白兩點即可:
-
第一,不要急於求成,保持初學者心態,分階段,分而治之。
-
第二,在每個階段的學習過程中,不要僅有輸入,更要保持輸出。
說是學習框架,其實也是一種認知框架。接下來,我們來看具體操作。
分階段學習
對於有一定編程基礎的朋友,學習 Rust 要經歷至少三個階段:
-
整體學習一遍 Rust 語法。對 Rust 語法和語言特性有一個充分了解。
-
Rust 基本所有權概念需要一定深入理解。
-
深入領域學習。上面兩個階段完成以後,就可以投入到領域實踐中,進一步深入學習。
這三個階段,面對不同經驗的學習者,學習時間可長可短,因人而異。在學習過程中,可以搭配一些項目,由簡入深。
要點就是,不要急於求成。
對於編程零基礎的朋友,則在遵循上面三個階段學習之前,需要補充一些必要的基礎:
-
計算機科學基礎,推薦一些快速入門的書籍:《計算機是如何工作的》、《程序是如何跑起來的》、《網絡是如何連接的》
-
入門一下 C 語言。入門 C 語言之後,學習 Rust 的時候有對比,更容易理解。
-
然後再遵循上面的三個階段來學習 Rust 。
第一階段:全面瞭解 Rust 語法
第一個階段的學習,目標是全面瞭解 Rust 語法。可以讓學習者在集中培訓前自行學習。
何爲掌握?
-
對 Rust 語法有一個比較全面的瞭解。
-
對 Rust 語法進行分類。
這個階段不是讓你一次性學會 Rust ,所以有些不理解的內容,也不要太鑽牛角尖,允許自己暫時不理解,最好能記錄一個問題清單。這個階段的重點在於全面瞭解 Rust 語法,在頭腦裏構建出語法體系結構,其中分類是重點。要對語法進行分門別類梳理。比如數據類型、控制流程、結構體、trait 和泛型、宏等等,它們分別的作用是什麼。
第一階段配套學習資料
-
《Rust 權威指南》[1],即 Rust 官方出品的 Rust Book 。
-
《Rust Cargo Book》[2]
-
其他免費或收費的入門類 Rust 資料。
看這些資料學習的時候,要圍繞第一階段的學習目標:全面瞭解 Rust 語法。
對 Rust 語法有一個基本瞭解之後,可以通過官方出品的 Rust by example[3] 和 Rustlings[4] 來檢驗自己的學習成果。
第一階段練手項目推薦
第一階段練手項目的選擇存在一些誤區,很多人喜歡用 Rust 來刷題來學習 Rust 。但其實刷題的效果並不好。
因爲 Rust 所有權的限制,對於實現一些算法和數據結構,沒有其他語言那麼靈活自由。如果沒有對 Rust 所有權有深入瞭解,那刷題遇到困難,比較容易放棄對 Rust 的學習,不容易堅持。
所以這個階段比較推薦的項目,還是以做一些讓自己容易產生成就感的項目比較好。總的原則就是:結合你自己的領域經驗,選擇簡單的項目入手。
這裏推薦一些練手項目:
-
結合官方的《Command Line Apps in Rust》[5] 一書,實現一個簡單的終端應用,比如讀取 CSV 文件之類。
-
去 GitHub 開源倉庫中尋找案例靈感:
-
比如實現一個終端打字練習的應用,比如 toipe[6] 。
-
或者是一個簡單的編輯器,比如 kyun [7] 。
-
從 《Rust Magazine》[8] 中尋找練手靈感。
-
其他,比如有些學習資料自身就配套應用案例。
當然,練手項目也比較適合集中培訓,由講師來帶領共同完成。
第二階段:掌握 Rust 語言關鍵概念
達成第一階段的學習目標之後,就可以開始第二階段的學習了。這一階段可以集中培訓。
第二階段的學習目標就是,掌握 Rust 語言的關鍵概念。主要包含如下概念:
-
所有權和借用檢查。
-
類型系統與編程範式。
-
Unsafe Rust 和 宏。
其中 「所有權和借用檢查」是重點,只有在掌握了這兩個概念之後,纔算入門 Rust 語言。至於其他概念,可以在邊做項目過程中逐漸掌握,但不能不知道它們。
第二階段配套學習資料推薦
-
《Rust 編程之道》
-
《Programming Rust》第二版
-
《Rust Design Patterns》[9]
-
Rust 標準庫文檔
-
《Rust 編碼規範》[10]
-
《Too Many lists》[11]
-
其他進階類 Rust 書目,以及免費或收費的學習資料。
這裏推薦的學習資料,不一定要全部都看完,可以着重去深入學習「所有權和借用檢查」這部分重點。然後去了解 「類型系統與編程範式」、「宏」和「Unsafe Rust」等概念,也可以深入瞭解 Rust 設計模式相關概念。
之後,再花時間深入閱讀一下 Rust 標準庫文檔,以及 學習 《Rust 編碼規範》。
經過上面的學習,就能爲投入 Rust 生產實踐打下良好的基礎。
第二階段練手項目推薦
這個階段比較推薦的項目,依然還是那個原則,即,結合你自己的領域經驗,選擇簡單的項目,由簡入深。與此同時,也可以開始閱讀一些比較知名的優秀項目源碼開始學習。
-
這個時候可以閱讀 《Too Many Lists》來實現一個鏈表,或者,可以去 LeetCode 刷題,藉此來檢驗自己對 Rust 所有權機制的理解。
-
GitHub 項目中獲取靈感:
-
smallvec[12],比如實現一個自定義的 Vector 集合容器
-
toydb[13],比如實現一個簡單的分佈式數據庫
-
其他。學習資料中本身推薦的案例,或者依據學習者擅長的領域來選擇適合的項目。
第三階段:深入領域學習
經過上面兩個階段的學習,學習者可以投入到自己的實際項目中開始學習了。如果沒有自己的實際項目,可以參與到開源項目的貢獻中去。
這個過程就是一個長期的學習和應用 Rust 的過程了。比如 Rust 併發和異步開發相關的內容,重點概念中關於類型系統、編程範式、宏、Unsafe Rust 的深入學習和應用,都在這個階段去完成。
保持輸入和輸出
學習的過程,要保持輸入和輸出平衡。
什麼叫輸入?從各種學習資源中汲取各種知識,叫輸入。
輸出的形式很多。寫一篇文章、參與一個項目、做一次分享,都是輸出。
只有輸入和輸出保持循環,人的大腦纔會處於思考模式,你輸入的東西纔會沉澱爲結構化記憶。
所以,在上述學習階段,除了輸入,還要讓自己保持輸出。這樣你的精力和時間纔不會白費。
參考資料
[1]
《Rust 權威指南》: https://doc.rust-lang.org/book/
[2]
《Rust Cargo Book》: https://doc.rust-lang.org/cargo/
[3]
Rust by example: https://doc.rust-lang.org/rust-by-example/
[4]
Rustlings: https://github.com/rust-lang/rustlings
[5]
《Command Line Apps in Rust》: https://rust-cli.github.io/book/index.html
[6]
toipe: https://github.com/Samyak2/toipe
[7]
kyun : https://github.com/file-acomplaint/kyun
[8]
《Rust Magazine》: https://rustmagazine.github.io/rust_magazine_2022/
[9]
《Rust Design Patterns》: https://rust-unofficial.github.io/patterns/
[10]
《Rust 編碼規範》: https://rust-coding-guidelines.github.io/rust-coding-guidelines-zh/
[11]
《Too Many lists》: https://rust-unofficial.github.io/too-many-lists/
[12]
smallvec: https://github.com/servo/rust-smallvec
[13]
toydb: https://github.com/erikgrinaker/toydb
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/3Y0AhB-BCkLCqk7aE_9cDQ