這是一個建立於
的文章,其中的資訊可能已經有所發展或是發生改變。
我已經花了不少時間在把玩一些新語言 – 特別要指出,Rust抓住了我的想象力。我們在Chef中使用大量的Ruby、Erlang和JavaScript(後來是Angular)代碼。以下是我喜歡這些語言的東西:
- Ruby的感覺就像永遠在敲打我頭腦中“whipuptitude”部分。它很容易,可以簡單的坐下來開始編碼,你基本不會碰到困難。它也有類似Perl中我很喜歡的表達力。你越熟練這個語言,你就會越覺得你好像可以用英語(母語)表達自己的想法。
- Erlang和OTP極好操作。那些模式比對、Actor並發、單一賦值,還有令人愉快的運行時導致運行、管理、調試產品服務是一種樂趣,我認為它文法是醜陋的,但是當你掌握它後,你會發現它的某種簡潔美。
- 現代JavaScript以它自己的方式變得越來越討人喜歡。比如你很容易就可以擷取社區貢獻的各種包和架構,像Angular那樣純粹的表現力,以及語言的經常使用部分的漸進式減肥都使體驗變得愉快。過去我不喜歡它。
所以 – 我決定寫一些Rust,還有Go,因為在我的世界裡,每個人似乎看起來對它都很著迷。
Rust
我幾個月前開始注意到Rust。這個語言被設計用來取代C/C++,適合進行底層開發,帶有高的安全性保障和革新性的記憶體管理方式(borrowing借用)。它還有我喜歡的和Erlang蠻類似的語言特性:模式比對、Actor樣式並發,預設不可變變數。
我使用C/C++的曆史並不多。誠實的講,我的強型別語言的編程經驗並不多。作為一個系統管理員,我們通常就是給某人的程式打補丁(我做了很多這種事,但打補丁不像從頭開發東西)。在我擁有的有限經驗中,我發現編譯->運行->排錯迴圈太令人惱火。我承認這是我個人的無知:如果我多花時間來理解語言,我一定可以發現發現那些定期打擊我的陷阱。
因此,我開始用Rust重寫一個Ruby開發的命令列工具。我無意推銷或者分享,它僅僅是我學習語言的一個借口(動力)。以下是我觀察到的:
Cargo包管理器非常好
Cargo是負責Rust專案管理的一個非常好的前端工具。建立一個新的Rust項目,添加測試、依賴等等都非常的容易和簡潔。
像指令碼語言一樣富有表現力
Rust就像一種非常富有表達力的底層指令碼語言。更多請看下面這個連結:
https://gist.github.com/adamhjk/e296257b32818ee8691d.js
有些東西像as_slice()和Vec也許需要一點時間來解釋,但它非常的直白。下面連結可以回顧這些函數:
https://gist.github.com/adamhjk/ead9de51d6f6d3aefeb2#file-review-rs
再次,我不認為寫Rus會比寫一種指令碼語言更難。這需要一點時間來適應事實,比如,我從have_dot_git(cwd)返回一個選項Option,並且用模式比對來抽取值(或者拋出錯誤)-但當你意識到引擎下面發生什麼事情後,你就會覺得這很棒。
Strongly typed 強型別
在所有的強型別語言中,我總是覺得我和編譯器在進行摔跤比賽。我發現很難信任編譯器,與其說它可以阻止我做一些傻事,還不如說它沒有理解我的方式。(我承認這是我自己的一種情感缺陷)Rust因以下這三個原因讓人覺得不同:
- 它的編譯錯誤資訊非常的清楚,直接指出哪裡錯了,還經常給你提供精準的解決方案(“你是不是想…”)。
- 編譯迴圈非常快,當My Code成功編譯後,它總是按我的想法準確的運行。
- 借用、使用期等概念需要點時間來習慣。但是,編譯器確實每次都代表你的利益,再次,錯誤提示資訊和規則是明確的。Rust沒有傳統的垃圾收集器-但它有非常清晰的規則來指示在棧和堆上的東西該活多久。這些規則和地區結合的很緊,在某種程度上,感覺很自然。
對於我最重要的是,My Code從來沒有segfaulted或者恐慌。這些都是我以前用底層系統程式設計語言中從來沒有擁有過的體驗。如果編譯器接受我的輸入,它開始運行-快速並且準確。
Rust有些庫還不存在
Rust還在進化,快到1.0了(譯者:現在1.2都出來了)。作為一個副作用,許多進階庫都還不存在,或者還沒被寫出來。一個好的(小)例子是命令列文法解析庫還不存在。有一個包包含在標準庫裡,但是介面效果不佳。Github中有一些有希望的庫,但是最好的那個(從介面、功能性等來看)沒有辦法用最新的Rust來編譯通過。(這是由於fail!(..)宏被改為panic!(..)-不是一件大事,但也是一件說明Rust還在演化的事實。)
同樣,Cargo可以很好的擷取依賴-但沒有說明那些包可以擷取,就像NPM、Rubygems或者CPAN那樣。
關於Rust的最終想法
Rust是強大的,高度深思熟慮的系統程式設計語言,帶有一些很好的、很有用的特性。(泛型、特質、模式比對、Actor並發、借用-不勝枚舉)。 那需要一下稅負來學習並用“Rust方法”來解決問題-語言本身是簡單的,但需要和一些不同的概念較勁。(譯者:如果你瞭解函數式編程Scala, Haskell,就會覺得學習Rust很快)
也就是說,我第一次覺得自己可以相信自己可以快速寫出一個快速、高效的底層系統代碼。編譯器非常友好,它提供的錯誤提示非常有用和清晰。當它演化到1.0,並且庫的生態系統開始升溫時-Rust將是一股不可忽視的力量。
Go
很多人說了很多關於Go如何神奇的事情。當我花了幾個小時用Go重構一些東西後,我明白了這個訴求。
Go比較小巧
如果你有一些C衍生語言的編程經驗,那麼你可以很快的學會這門語言的一些表面領域。有很多東西你已經知道如何在語言中使用了:if/then /else,switch,for。它們的使用文法你已經知道了。它提供一些速記文法來簡化一些類型冗長的打字工作。(比如 :=)。
Go是自以為是的 – 關乎很多事情
當你讀“ 怎麼編寫Go代碼 ”時,它就開始告訴你怎樣從頂層原始碼目錄開始的每件東西你該怎麼用Go寫。Go的工具鏈知道怎樣取得結構和做正確的事情-編譯二進位到你的’bin’目錄,運行你的測試,捕獲依賴。
靜態輸出是好的-和現實,任何你本地編譯的都會是你使用者所消費的,感覺不錯。
Go避免你的方法
Rust編譯器讓你很確定你的想法會如何在底層代碼中工作,Go坐在中間。語言是強型別的,但在實踐中,它大部分時間都似乎可以推斷出你的意圖。舉例:
https://gist.github.com/adamhjk/5a475b8dd45971a4e814#file-dot_git_dir-go
在函數中唯一的類型注釋是輸入和輸出-其他的每件事就是工作。感覺快速、容易、平易近人和非常少的麻煩。
Go的運行時失敗
Rust運行時非常非常難出錯。編譯器讓我確信我檢查了每一個代碼路徑,總是確保我覆蓋了每個角落。Go很樂意做我告訴它的東西 – 雖然編譯器會阻止我的愚蠢,但它不會阻止我做這樣的事:
https://gist.github.com/adamhjk/9c7eae1d053a1788f581#file-panic-go
在第九行盲目的假設正運算式找到匹配,然後導致執行階段錯誤資訊。這在Rust中絕不會發生。
https://gist.github.com/adamhjk/2eb74d326242a9093f9e#file-current_branch-rs
因為regex捕獲的傳回型別是Option選項,編譯器知道我需要處理所有可能的值。我真的不能選擇忽略它。這在我寫代碼的時候就發生了-在Go 中,我唯寫了我認為我想要的,然後在運行時才瞭解哪裡錯了(這是個很小的fix)。在Rust中,編譯器在我第一次嘗試這個函數時告訴我,我還沒有對 Option傳回值處理None結果。
速度,可訪問性,還有庫
權衡是有趣的。Go代碼用更少的時間來寫,語言容易訪問,生態系統強大。它讓我感覺在用指令碼語言在工作,但同時避免了大多數惡名昭著的錯誤。因為唯一的語言結構是最常見結構,在語言中感覺很淺顯,根本沒有時間。
Go有巨大的庫生態系統,一個清晰的方式來尋找它們,和一個簡單的方式來得到它們。
所以...Rust還是Go?
我想,務實的回答是‘物盡其善,那個實用用哪個’。Go可以替代人們用Ruby、Pythong或者Perl所寫的東西。它是一個簡單,平易近人的語言,加上強型別和難以置信的生態系統。我明白人們為什麼喜歡它。靜態二進位,很好的生態系統,配合的很好。我寫Go代碼大概比Rust快一倍。
但是,我更喜歡Rust。我喜歡它有模式比對、泛型、預設的不可變資料。我喜歡如果My Code編譯通過,程式按我設計的意願啟動並執行可能性是極高的。當我想象一個生態系統將在這樣的一個基礎上建立出來時,我願意活在那個世界裡。這比我依賴大量語言用例,並且讓我沒有真正感覺到舒適的空間的世界要好。我很確定如果你用C/C++的話,Rust將非常吸引你。而你用Ruby或Python的話Go對你更有吸引力。然而,我想一旦Rusts生態系統起飛,它將同時吸引那些使用Ruby/Python的人。
我想起了一次高層招聘規則擷取的教訓,規則之一是他/她必須在某些方面讓人驚訝一個在很多方面“好”的人,通常來說不是偉大的。Go就是給我這種感覺-它在每一方面都好,但沒有抓住我的心,沒有讓我覺得因為在我已有的生態系統裡面沒有這些東西而覺得非常興奮,Rust絕對驚人的保證你寫的代碼是在運行時正確和安全的-這是一種啟示。
你一定要兩者同時試一下。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。