- Rust實戰
- (新西蘭)蒂姆·麥克納馬拉
- 1871字
- 2022-12-01 19:12:21
1.5 使用Rust語言的感受如何?
Rust是Haskell和Java程序員可以用得很順手的編程語言。在實現了低級的、裸機性能的同時,Rust也提供了接近于Haskell和Java之類的動態語言的高級表達能力。
在1.3節中,我們看到了幾個“Hello, world!”的例子。接下來,為了對Rust的一些特性有更好的了解,讓我們來嘗試一些稍微復雜點兒的東西。清單1.2簡單介紹了Rust對于基本的文本處理可以做些什么。此清單的源代碼保存在ch1/ch1-penguins/src/main.rs文件中。一些需要關注的語言特性如下。
● 常用的流程控制機制:包括for
循環和continue
關鍵字。
● 方法語法:雖然Rust不是面向對象的,因為它不支持繼承,但是Rust用到了面向對象語言里的方法語法。
● 高階編程:函數可以接收和返回函數。舉例來說,在代碼第19行(.map(|field| field.trim())
)中有一個閉包(closure),也叫作匿名函數或lambda函數。
● 類型注解:雖然需要用到類型注解的地方相對是較少的,但有時又必須要用到類型注解,作為給編譯器的提示信息,比如,代碼中以if let Ok(length)
開頭的那一行(第27行)。
● 條件編譯:在清單1.2中,第21~24行的代碼(if cfg!(...);
)不會被包含到該程序的發布構建(release build)當中。
● 隱式返回:Rust提供了return
關鍵字,但通常情況下會將其省略。Rust是一門基于表達式的語言。
清單1.2 Rust代碼示例,展示了對CSV數據的一些基本處理
1 fn main() { ?--- 在可執行的項目中,main() 函數是必需的。
2 let penguin_data = "\ ?--- 忽略掉末尾的換行符。
3 common name,length (cm)
4 Little penguin,33
5 Yellow-eyed penguin,65
6 Fiordland penguin,60
7 Invalid,data
8 ";
9
10 let records = penguin_data.lines();
11
12 for (i, record) in records.enumerate() {
13 if i == 0 || record.trim().len() == 0 { ?--- 跳過表頭行和只含有空白符的行。
14 continue;
15 }
16
17 let fields: Vec <_> = record ?--- 從一行文本開始。
18 .split(',') ?--- 將record分割(split)為多個子字符串。
19 .map(|field| field.trim()) ?--- 修剪(trim)掉每個字段中兩端的空白符。
20 .collect(); ?--- 構建具有多個字段的集合。
21 if cfg!(debug_assertions) { ?--- cfg!用于在編譯時檢查配置。
22 eprintln!("debug: {:?} -> {:?}",
23 record, fields); ?--- eprintln!用于輸出到標準錯誤(stderr)
24 }
25
26 let name = fields[0];
27 if let Ok(length) = fields[1].parse:: <f32>() { ?--- 試圖把該字段解析為一個浮點數。
28 println!("{}, {}cm", name, length); ?--- println!用于輸出到標準輸出(stdout)。
29 }
30 }
31 }
清單1.2可能會讓有些讀者感到困惑,尤其是那些以前從未接觸過Rust的人。在繼續前進之前,我們給出一些簡單的說明。
● 第17行變量fields
的類型注解為Vec<_>
。Vec類型是動態數組,是vector的縮寫,它是一個可以動態擴展的集合類型。此處的下畫線(_)表示,要求Rust推斷出此動態數組的元素類型。
● 在第22行和第28行,我們要求Rust把信息輸出到控制臺上。eprintln!
會輸出到標準錯誤,而println!
會將其參數輸出到標準輸出。 - 宏類似于函數,但它返回的是代碼而不是值。通常,宏用于簡化常見的代碼模式。 - eprintln!
和println!
都是在其第一個參數中使用一個字符串字面量,并嵌入了一個迷你語言來控制它們的輸出。其中的占位符{ }則表示Rust應該使用程序員定義的方法,將該值表示為一個字符串,而{:?}則表示要求使用該值的默認表示形式。
● 第27行包含一些新奇的特性。if let Ok(length) = fields[1].parse::<f32>()
意為“嘗試著把fields[1]解析為一個32位浮點數,如果解析成功,則把此浮點數賦值給length變量”。if let
結構是一種有條件地處理數據的簡明方法,且具備把該數據賦值給局部變量的功能。如果成功解析字符串,parse()
方法會返回Ok(T)
(這里的T
代表任何類型);反之,如果解析失敗,它會返回Err(E)
(這里的E
代表一個錯誤類型)。if let Ok(T)
的效果就是忽略任何錯誤的情況,比如在處理Invalid,data
這一行時就會出現錯誤。 - 如果Rust無法從環境上下文中推斷出類型,就會要求你指定這些類型。在這里調用parse()
的代碼為parse :: <f32>()
,其中就有一個內嵌的類型注解。
把源代碼轉換為一個可執行文件的過程叫作編譯。要編譯Rust代碼,我們需要安裝Rust編譯器并針對此源代碼執行編譯。編譯清單1.2需要采用以下步驟。
(1)打開一個控制臺(例如cmd.exe、PowerShell、Terminal或Alacritty)。
(2)找到所下載的源代碼,然后進入ch1/ch1-penguins目錄(注意:不是ch1/ch1-penguins/src目錄)。
(3)執行cargo run
。
輸出的結果如下所示:
$ cargo run
Compiling ch1-penguins v0.1.0 (../code/ch1/ch1-penguins)
Finished dev [unoptimized + debuginfo] target(s) in 0.40s
Running 'target/debug/ch1-penguins'
debug: " Little penguin,33" -> ["Little penguin", "33"]
Little penguin, 33cm
debug: " Yellow-eyed penguin,65" -> ["Yellow-eyed penguin", "65"]
Yellow-eyed penguin, 65cm
debug: " Fiordland penguin,60" -> ["Fiordland penguin", "60"]
Fiordland penguin, 60cm
debug: " Invalid,data" -> ["Invalid", "data"]
你會注意到,以debug:開頭的這些輸出行會帶來干擾。我們可以用cargo命令的--release標志項編譯出一個發布構建的版本,這樣就可以消除這些干擾的輸出行了。這個條件編譯功能是由cfg
!(debug_assertions){
… }
代碼塊提供的,如清單1.2的第21~24行所示。發布構建在運行時要快得多,但是需要更長的編譯期:
$ cargo run --release
Compiling ch1-penguins v0.1.0 (../code/ch1/ch1-penguins)
Finished release [optimized] target(s) in 0.34s
Running 'target/release/ch1-penguins'
Little penguin, 33cm
Yellow-eyed penguin, 65cm
Fiordland penguin, 60cm
給cargo
命令再添加一個-q
標志項,還能進一步減少輸出信息。q
是“quiet”的縮寫。具體的用法如下:
$ cargo run -q --release
Little penguin, 33cm
Yellow-eyed penguin, 65cm
Fiordland penguin, 60cm
清單1.1和清單1.2的代碼示例,挑選了盡可能多的、有代表性的Rust特性,并把它們打包到易于理解的例子中。希望這些示例能展示出Rust程序既有低級語言的性能,又能給人帶來高級語言的編程感受。現在,讓我們從具體的語言特性中后退一步,思考Rust語言背后的一些思想,以及這些思想在Rust編程語言的生態系統中的地位。
[11] 參見Chrome OS KVM—A component written in Rust.
- scikit-learn Cookbook
- Rust編程從入門到實戰
- Unity 2020 Mobile Game Development
- Java應用開發技術實例教程
- Windows Forensics Cookbook
- H5頁面設計:Mugeda版(微課版)
- 微信小程序開發與實戰(微課版)
- TMS320LF240x芯片原理、設計及應用
- Processing創意編程指南
- Buildbox 2.x Game Development
- Principles of Strategic Data Science
- Clojure for Java Developers
- C編程技巧:117個問題解決方案示例
- 從Excel到Python數據分析:Pandas、xlwings、openpyxl、Matplotlib的交互與應用
- Instant Zurb Foundation 4