這些情況會阻礙你學習Rust語言 - dystroy

banq發表於2021-12-16

我見過優秀的程式設計師努力學習 Rust,甚至放棄。我自己也遇到了一些困難。
以下是我所看到的可能導致您無法學習 Rust 的錯誤。我希望這份清單能幫助你避免它們。
 

錯誤一:沒有準備好邁出第一步
學習 Rust 的最糟糕的方法是在完成繁重的工作後,在晚上的零星短時間裡模糊地觀察它,或者嘗試一些小東西。當然,您之前確實學習過一些這樣的語言,因此您可能對自己的能力充滿信心。但是在 Rust 的某個時刻,它可能很快就會到來,你會遇到一個更高的步驟,如果你不以專注和奉獻精神來對抗它,你就有可能無法克服它。
這可能令人沮喪。有些人放棄了。
如果你變得陳舊而你想走得更遠,你應該

  1. 理解這很正常,因為 Rust 有不同的概念,你必須學習
  2. 不嘗試就停止嘗試,你是在浪費時間和動力
  3. 用專門的時間和精力回到戰鬥中

 

錯誤二:不看書就進入潛水
Rust 很大,並不是所有的事情都可以透過亂七八糟的方式變得顯而易見。重要的是,您至少注意到了特徵、宏、智慧指標等,並且本書提供了對所有主要概念的簡短介紹。
所以在你潛水之前,先對這本書(或幾本書)有個大概的瞭解。也許沒有完全閱讀它,但請確保已閱讀所有標題,以便您知道以後何時返回。
  

錯誤 3:從實施過時的技術解決方案(如演算法和資料結構)開始
舊的 CS 課程充滿了數學上漂亮的演算法或資料結構,它們在白板或學習練習中反覆使用。
最引人注目的例子是連結串列及其變體。
我總是看到新手來到 Stack Overflow 並詢問如何編寫它們。
這些結構是

  • 在最近的硬體中通常效率很低(並且大 O 表示法的指令數不會告訴你有多少)
  • 在 Rust 中很難做到

直接的簡單答案是“在瞭解 Rust 之前不要嘗試這些”。
稍後您可能會意識到您不需要它們,但與此同時,請相信使用連結串列學習 Rust 是一個非常糟糕的主意。
這是這篇著名的文章中首先觀察到,連結串列仍然是新來者最喜歡沉船的暗礁之一。
  

錯誤 4:不閱讀編譯器錯誤
您可能習慣於編譯器錯誤充其量只是指向您無法理解含義區域的模糊指標。
它在 Rust 中不起作用。Rust 的編譯器是你最好的老師,他準確地解釋了問題並提出瞭解決方案。
所以,我建議

  • 請注意您的 IDE 不會隱藏或截斷編譯器的輸出
  • 注意編譯器錯誤的準確措辭
  • 閱讀建議

至少在開始時,檢視錯誤的最佳方法是cargo check在您的控制檯中執行。
 

錯誤 5:忽視編譯器警告
你必須在兩個時刻檢視警告:

  • 當出現編譯器錯誤而你不明白為什麼
  • 當你的小任務完成並且沒有錯誤時,在你提交甚至測試之前

已完成程式碼中的大多數警告實際上是錯誤。
 

錯誤 6:應用其他語言的最佳實踐
在編寫 Rust 時,使您成為其他語言的優秀程式設計師的大部分內容仍然有效,但在涉及簡單的最佳實踐時不要急於求成。它們可能無用、適得其反或在 Rust 中沒有任何意義。

  • 嘗試讓 Rust 看起來像 OOP

當您不知道從哪裡開始時,構建分層類樹可能很誘人。您可能想說汽車顯然是車輛,而卡車是汽車的一種,或者反過來說。
只是不要。不要尋找模擬繼承的技巧。Rust 不是這樣設計的,嘗試使它成為 OOP 也無濟於事。
  • 堅持讓它發揮作用

你喜歡純函式,對吧?副作用是你的剋星,所以你要確保你只使用純函式結構。
事實證明,函數語言程式設計背後的一個動機問題在 Rust 中以另一種方式解決。
當我們說 Rust 的所有權模型確保記憶體安全時,人們通常認為這意味著不會有建立前使用或釋放​​後使用或類似錯誤。它實際上更強大:對某些資料結構只有一個可變引用(即獨佔引用)意味著大多數資料不一致的來源也被刪除。
因此,您可以在 Rust 中使用函式式風格,並且在 Rust 努力在編譯時為抽象付費的意義上,它通常是低成本的,但是當它不起作用時,您不應該強迫自己堅持該風格。
在 Rust 中,當您的函式程式碼開始看起來難以破譯並且編寫起來很痛苦時,問問自己一個好的舊for迴圈是否會更好。
  • 構建不可變的結構和集合

直截了當地說,你不需要它們,再次感謝 Rust 的所有權模型。不放棄可變引用可以解決大多數問題。
  • 防禦性程式設計

除了Option“十億美元的錯誤”,Result而不是例外,以及 Rust 列舉的其他用途(允許您僅為相關變體設定欄位),您在實踐中幾乎不會發現資料不一致的情況。
  • 使用虛擬值

沒有那個必要。
舊程式碼:

let mut a = 0;
if some_expr() {
    a = some_fun();
} else {
    a = some_other_fun();
}

新程式碼:

let a = if some_expr() {
    some_fun()
} else {
    some_other_fun()
};


 

錯誤 7:構建生命週期重的 API
編寫庫很痛苦,因為我必須在任何地方都考慮生命週期。你不能只是擺脫它們。
當我設計我的第一個主要庫Termimad 時,我希望能夠以儘可能好的效能和儘可能少的記憶體成本使用它。在庫的第一個版本中(更具體地說是我並行開發的 Minimad 依賴項),String這個文字操作箱的任何結構中都沒有。我只使用引用,到處都是引用。
第一個問題是直接的:編寫庫很痛苦,因為我必須在任何地方都考慮生命週期。你不能只是擺脫它們。
後來我發現了第二個問題,而且問題更深:由於需要擁有資料,API 的許多用法變得更加困難,或者效率更低。
當結構體引用資料時,您必須保留引用的資料。當它是一些動態資料時,這可能會很煩人:你不能只傳遞結構而忘記底層資料(好吧,你可以但你不想)。
這個問題沒有通用的解決方案。我建立了替代結構,以幫助在 Termimad 中處理它,但我仍然後悔最初沒有做出讓我的庫結構擁有資料的簡單選擇。
不是每個人都會犯這個錯誤,但那些犯錯的人可能會為此付出很長時間。
對於新的 Rust 開發人員來說,如何避免這個錯誤的簡短初始版本是:在設計新庫的結構時,更喜歡擁有資料。不要過早地使用基於引用的結構進行最佳化。
因為克隆資料以將它們傳遞給 API 很容易(而且成本也不高),但有時保留資料以便您可以傳遞引用是非常痛苦的。
 

錯誤 8:忽視非標準庫
如果標準庫中似乎沒有某些東西(有時甚至是),請查詢“非標準”庫。
例如,這些 crate 是許多程式使用的標準的、高質量的庫,你不能像忽略它們一樣忽略它們std:

  • regex : 每個人如何在 Rust 中使用正規表示式
  • crossbeam : 一個高效便捷的通道庫
  • serde:在 Rust 中進行序列化和反序列化的自然方式
  • rayon:一個非常簡單易用的資料並行庫
  • rand : 偽隨機生成的預設選擇

有許多問題存在多種解決方案,因此選擇不會很明顯,但很容易找到它們並進行比較。詢問谷歌並搜尋crates.iolib.rs,閱讀自述檔案(忽略“極快”的斷言)並檢查星星和家屬的數量,四處詢問。
 

錯誤九:使用unsafe、濫用unwrap
nsafe是很有用,是的,它是用來使用的。
但是您在學習 Rust 時可能不需要它。
如果您正在構建一些正常的東西,並且您遇到了文件中要求的unsafe函式,請再看一遍:附近可能有一個安全的解決方案。並且unsafe不是偷工減料並使程式碼更快的神奇解決方案。
至於unwrap,它在面向新程式設計師的文獻中有點過於存在,因為它出現在大多數 Stack Overflow 答案和大多數文件片段中。
。。。
一個流行的中間立場,在原型設計或編寫一個簡短的片段時,使用expect來幫助說明為什麼你認為這種情況不應該發生。
選擇一種流行的錯誤管理庫,在需要時使用Result正確宣告你的函式,你的生活會更輕鬆。
 

錯誤10:不看資料
Rust 文件通常被認為是優秀的。
您閱讀精美原始碼的次數越多,您編寫精美程式碼的速度就越快。
 

錯誤 11:從一開始就設計一切
Rust 使重構變得特別容易:編譯器會指導您進行更改,直到程式碼再次保持一致。
一磚一瓦地構建您的東西並並行完善全域性計劃,它不需要完整或保持不變
 

相關文章