官术网_书友最值得收藏!

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.

主站蜘蛛池模板: 乌鲁木齐市| 宣恩县| 汶川县| 浦城县| 五莲县| 周至县| 红河县| 泽库县| 湖口县| 江阴市| 甘南县| 吴堡县| 余干县| 迁安市| 突泉县| 临桂县| 新泰市| 南召县| 金秀| 永安市| 鄂托克旗| 平塘县| 阜康市| 涞源县| 精河县| 株洲市| 余江县| 长垣县| 遂平县| 晴隆县| 穆棱市| 西昌市| 马公市| 汤阴县| 平定县| 山东| 灵台县| 砚山县| 邓州市| 丘北县| 高碑店市|