第10ç« æä¸¾å模å¼
# 第10ç« æä¸¾å模å¼
令人æè®¶çæ¯ï¼å¾å¤è®¡ç®æºç¸å ³æ¦å¿µï¼è¥è§ä½å¯¹åç±»åï¼sum typesï¼ç严é缺失ï¼å¯å¯¹æ¯å¯¹lambda表达å¼çç¼ºå¤±ï¼æ¥çè§£ï¼å°±è¯´å¾éäºã ââæ ¼é·ç»Â·éå°ï¼Graydon Hoareï¼
æ¬ç« ç第ä¸ä¸ªä¸»é¢å¾å¼ºå¤§ï¼ç±æ¥å·²ä¹
ï¼è½è®©ä½ é«æå®æè®¸å¤ä»»å¡ï¼å½ç¶è¦ä»åºä¸ç¹ä»£ä»·ï¼ï¼å¨ä¸åæåä¸æè®¸å¤ä¸åçç§°å¼ãä½å®å¹¶éæ¶éï¼èæ¯ä¸ç§ç¨æ·èªå®ä¹æ°æ®ç±»åãå¨MLåHaskellç¨åºåä¸ï¼å®æ©å°±è¢«ç§°ä¸ºåç±»åï¼sum typesï¼ã带æ è®°èåï¼discriminated unionsï¼æä»£æ°æ°æ®ç±»åï¼algebraic data typesï¼ãå¨Rustä¸ï¼å®ä»¬è¢«ç§°ä¸ºæä¸¾ï¼enumerationsï¼ï¼ç®ç§°enumã䏿¶éä¸åï¼å®ä»¬é常å®å
¨ï¼è䏿éç代价ä¹ä¸ç®å¤§ã
C++åC#䏿æä¸¾ï¼ä½ å¯ä»¥ç¨å®ä»¬å®ä¹èªå·±çç±»åï¼å
¶å¼æ¯ä¸ç»å½å常éãä¾å¦ï¼ä½ å¯è½å®ä¹ä¸ä¸ªå为Colorçç±»åï¼å
¶å¼æRedï¼çº¢è²ï¼ãOrangeï¼æ©è²ï¼ãYellowï¼é»è²ï¼ççãè¿ç§æä¸¾å¨Rustä¸åæ ·å¯ç¨ãä¸è¿ï¼Rust对æä¸¾çè¿ç¨æ´ä¸ºæ·±å
¥ãRustä¸çæä¸¾è¿å¯ä»¥å
嫿°æ®ï¼çè³æ¯ä¸åç±»åçæ°æ®ãä¾å¦ï¼RustçResult<String, io::Error>ç±»åå°±æ¯ä¸ä¸ªæä¸¾ï¼è¿æ ·çå¼è¦ä¹æ¯å
å«StringçOkå¼ï¼è¦ä¹æ¯å
å«io::ErrorçErrå¼ãè¿è¶
åºäºC++åC#䏿䏾çè½åèå´ï¼å®æ´åæ¯Cè¯è¨ä¸çèåï¼unionï¼ââä½ä¸èåä¸åï¼Rustä¸çæä¸¾æ¯ç±»åå®å
¨çã
åªè¦ä¸ä¸ªå¼å¯è½æ¯å¤ç§æ åµä¸çæä¸ç§ï¼æä¸¾å°±å¾æç¨ãä½¿ç¨æä¸¾ç âä»£ä»·â æ¯ï¼ä½ å¿ é¡»ä½¿ç¨æ¨¡å¼å¹é ï¼è¿æ¯æ¬ç« ååé¨åç主é¢ï¼æ¥å®å ¨å°è®¿é®æ°æ®ã
å¦æä½ ä½¿ç¨è¿Pythonä¸çè§£å ï¼unpackingï¼æJavaScriptä¸çè§£æï¼destructuringï¼ï¼é£ä¹å¯¹æ¨¡å¼ï¼Patternsï¼å¯è½ä¼æäºçæï¼ä½Rust对模å¼çè¿ç¨æ´æ·±å ¥ãRustæ¨¡å¼æç¹åç¨äºå¤çæææ°æ®çæ£å表达å¼ï¼ç¨äºæµè¯ä¸ä¸ªå¼æ¯å¦å ·æç¹å®çææç»æãå®ä»¬å¯ä»¥ä¸æ¬¡æ§ä»ç»æä½æå ç»ä¸æåå¤ä¸ªå段并èµå¼ç»å±é¨åéã忣å表达å¼ä¸æ ·ï¼å®ä»¬å¾ç®æ´ï¼é常åªç¨ä¸è¡ä»£ç å°±è½å®ææææä½ ã
æ¬ç« 仿䏾çåºç¡ç¥è¯å¼å§ï¼å±ç¤ºå¦ä½å°æ°æ®ä¸æä¸¾åä½å
³èï¼ä»¥åæä¸¾å¨å
åä¸çå卿¹å¼ãç¶åæä»¬å°å±ç¤ºRustçæ¨¡å¼åmatchè¯å¥å¦ä½åºäºæä¸¾ãç»æä½ãæ°ç»ååçç®æ´å°æå®é»è¾ã模å¼è¿å¯ä»¥å
å«å¼ç¨ãç§»å¨æä½åifæ¡ä»¶ï¼è¿è®©å®ä»¬çåè½æ´å¼ºå¤§ã
# æä¸¾
ç®åçC飿 ¼æä¸¾å¾ç´æ¥ï¼
enum Ordering {
Less,
Equal,
Greater,
}
2
3
4
5
è¿å£°æäºä¸ä¸ªå为Orderingçç±»åï¼å®æä¸ä¸ªå¯è½çå¼ï¼ç§°ä¸ºåä½ï¼variantsï¼ææé å¨ï¼constructorsï¼ï¼Ordering::LessãOrdering::EqualåOrdering::Greaterãè¿ä¸ªç¹å®çæä¸¾æ¯æ ååºçä¸é¨åï¼æä»¥Rust代ç å¯ä»¥è¿æ ·å¯¼å
¥å®ï¼
use std::cmp::Ordering;
fn compare(n: i32, m: i32) -> Ordering {
if n < m {
Ordering::Less
} else if n > m {
Ordering::Greater
} else {
Ordering::Equal
}
}
2
3
4
5
6
7
8
9
10
11
æè å¯¼å ¥å®çæææé å¨ï¼
use std::cmp::Ordering::{self, *}; // `*` ç¨äºå¯¼å
¥ææå项
fn compare(n: i32, m: i32) -> Ordering {
if n < m {
Less
} else if n > m {
Greater
} else {
Equal
}
}
2
3
4
5
6
7
8
9
10
导å
¥æé å¨åï¼æä»¬å¯ä»¥ç´æ¥åLessè䏿¯Ordering::Lessï¼ä¾æ¤ç±»æ¨ãä½ç±äºè¿æ ·ä¸å¤ªæç¡®ï¼æä»¥ä¸è¬è®¤ä¸ºï¼é¤éè½è®©ä»£ç å¯è¯»æ§å¤§å¤§æé«ï¼å¦åæå¥½ä¸è¦è¿æ ·å¯¼å
¥ã
è¦å¯¼å
¥å½å模åä¸å£°æçæä¸¾çæé å¨ï¼å¯ä»¥ä½¿ç¨self导å
¥ï¼
enum Pet {
Orca,
Giraffe,
...
}
use self::Pet::*;
2
3
4
5
6
å¨å åä¸ï¼C飿 ¼æä¸¾çå¼åå¨ä¸ºæ´æ°ãå¶å°éè¦åè¯Rust使ç¨åªäºæ´æ°ï¼
enum HttpStatus {
Ok = 200,
NotModified = 304,
NotFound = 404,
...
}
2
3
4
5
6
å¦åï¼Rustä¼ä»0å¼å§ä¸ºä½ åé è¿äºæ°åã
é»è®¤æ åµä¸ï¼Rust使ç¨è½å®¹çº³C飿 ¼æä¸¾çæå°å ç½®æ´æ°ç±»åæ¥åå¨å®ä»¬ã大夿°C飿 ¼æä¸¾å¯ä»¥ç¨ä¸ä¸ªåè表示ï¼
use std::mem::size_of;
assert_eq!(size_of::<Ordering>(), 1);
assert_eq!(size_of::<HttpStatus>(), 2); // 404 æ æ³ç¨u8表示
2
3
ä½ å¯ä»¥éè¿ç»æä¸¾æ·»å #[repr]屿§æ¥è¦çRust对å
å表示çéæ©ã详ç»å
å®¹è§ â寻æ¾éç¨æ°æ®è¡¨ç¤ºå½¢å¼âã
å°C飿 ¼æä¸¾è½¬æ¢ä¸ºæ´æ°æ¯å 许çï¼
assert_eq!(HttpStatus::Ok as i32, 200);
ç¶èï¼åè¿æ¥ä»æ´æ°è½¬æ¢ä¸ºæä¸¾æ¯ä¸å 许çãä¸CåC++ä¸åï¼Rustä¿è¯æä¸¾å¼åªè½æ¯æä¸¾å£°æä¸ååºçå¼ä¹ä¸ã仿´æ°ç±»åå°æä¸¾ç±»åçæªç»æ£æ¥ç转æ¢å¯è½ä¼ç ´åè¿ä¸ªä¿è¯ï¼æä»¥æ¯ä¸å 许çãä½ å¯ä»¥èªå·±ç¼åä¸ä¸ªæ£æ¥è½¬æ¢ç彿°ï¼
fn http_status_from_u32(n: u32) -> Option<HttpStatus> {
match n {
200 => Some(HttpStatus::Ok),
304 => Some(HttpStatus::NotModified),
404 => Some(HttpStatus::NotFound),
...
_ => None,
}
}
2
3
4
5
6
7
8
9
æè
使ç¨enum_primitiveåºãå®å
å«ä¸ä¸ªå®ï¼å¯ä»¥èªå¨ä¸ºä½ çæè¿ç±»è½¬æ¢ä»£ç ã
åç»æä½ä¸æ ·ï¼ç¼è¯å¨ä¼ä¸ºä½ å®ç°ä¸äºåè½ï¼æ¯å¦==è¿ç®ç¬¦ï¼ä½ä½ éè¦æ¾å¼è¦æ±ï¼
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum TimeUnit {
Seconds,
Minutes,
Hours,
Days,
Months,
Years,
}
2
3
4
5
6
7
8
9
æä¸¾ä¹å¯ä»¥åç»æä½ä¸æ ·ææ¹æ³ï¼
impl TimeUnit {
/// è¿åè¿ä¸ªæ¶é´åä½ç夿°åè¯å½¢å¼ã
fn plural(self) -> &'static str {
match self {
TimeUnit::Seconds => "seconds",
TimeUnit::Minutes => "minutes",
TimeUnit::Hours => "hours",
TimeUnit::Days => "days",
TimeUnit::Months => "months",
TimeUnit::Years => "years",
}
}
/// è¿åè¿ä¸ªæ¶é´åä½çåæ°åè¯å½¢å¼ã
fn singular(self) -> &'static str {
self.plural().trim_end_matches('s')
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
å ³äºC飿 ¼æä¸¾å°±ä»ç»å°è¿éãRust䏿´æè¶£çæä¸¾ç±»åæ¯å ¶åä½å¯ä»¥æææ°æ®çæä¸¾ãæä»¬å°å±ç¤ºè¿äºæä¸¾å¨å åä¸çå卿¹å¼ï¼å¦ä½éè¿æ·»å ç±»ååæ°ä½¿å ¶æä¸ºæ³åï¼ä»¥åå¦ä½ç¨æä¸¾æå»ºå¤æçæ°æ®ç»æã
# å 嫿°æ®çæä¸¾
æäºç¨åºæ»æ¯éè¦ç²¾ç¡®æ¾ç¤ºæ¥æåæ¶é´ï¼ç²¾ç¡®å°æ¯«ç§ï¼ä½å¯¹äºå¤§å¤æ°åºç¨ç¨åºæ¥è¯´ï¼ä½¿ç¨å¤§è´çè¿ä¼¼å¼ï¼æ¯å¦ â两个æåâï¼ä¼æ´å好ãæä»¬å¯ä»¥ç¨ä¹åå®ä¹çæä¸¾æ¥å®ç°è¿ä¸ç¹ï¼
/// æ
æåæ´çæ¶é´æ³ï¼è¿æ ·æä»¬çç¨åºä¼æ¾ç¤º â6个æåâï¼è䏿¯ â2016å¹´2æ9æ¥ä¸å9:49âã
#[derive(Copy, Clone, Debug, PartialEq)]
enum RoughTime {
InThePast(TimeUnit, u32),
JustNow,
InTheFuture(TimeUnit, u32),
}
2
3
4
5
6
7
è¿ä¸ªæä¸¾ä¸ç两个åä½InThePaståInTheFutureæ¥ååæ°ï¼è¿äºè¢«ç§°ä¸ºå
ç»åä½ï¼tuple variantsï¼ãåå
ç»ç»æä½ä¸æ ·ï¼è¿äºæé 卿¯å建æ°RoughTimeå¼ç彿°ï¼
let four_score_and_seven_years_ago =
RoughTime::InThePast(TimeUnit::Years, 4 * 20 + 7);
let three_hours_from_now =
RoughTime::InTheFuture(TimeUnit::Hours, 3);
2
3
4
æä¸¾ä¹å¯ä»¥æç»æä½åä½ï¼struct variantsï¼ï¼å®ä»¬å å«å ·ååæ®µï¼å°±åæ®éç»æä½ä¸æ ·ï¼
enum Shape {
Sphere { center: Point3d, radius: f32 },
Cuboid { corner1: Point3d, corner2: Point3d },
}
let unit_sphere = Shape::Sphere { center: ORIGIN, radius: 1.0, };
2
3
4
5
6
æ»ä½èè¨ï¼Rustæä¸ç§æä¸¾åä½ï¼ä¸æä»¬å¨ä¸ä¸ç« ä»ç»çä¸ç§ç»æä½ç¸å¯¹åºã
æ²¡ææ°æ®çåä½å¯¹åºäºç±»åå ç»æä½ãå ç»åä½çå¤è§ååè½é½ä¸å ç»ç»æä½ç±»ä¼¼ãç»æä½åä½æè±æ¬å·åå ·ååæ®µãä¸ä¸ªæä¸¾å¯ä»¥åæ¶å å«è¿ä¸ç§åä½ï¼
enum RelationshipStatus {
Single,
InARelationship,
ItsComplicated(Option<String>),
ItsExtremelyComplicated {
car: DifferentialEquation,
cdr: EarlyModernistPoem,
},
}
2
3
4
5
6
7
8
9
æä¸¾çæææé å¨ååæ®µä¸æä¸¾æ¬èº«å ·æç¸åçå¯è§æ§ã
# æä¸¾å¨å åä¸çåå¨
å¨å åä¸ï¼å 嫿°æ®çæä¸¾åå¨ä¸ºä¸ä¸ªå°æ´æ°æ ç¾ï¼åå ä¸è¶³å¤å®¹çº³æå¤§å使æå段çå å空é´ãæ ç¾å段ç±Rustå é¨ä½¿ç¨ï¼å®è¡¨ææ¯åªä¸ªæé å¨å建äºè¿ä¸ªå¼ï¼è¿è表æè¯¥å¼æåªäºå段ã
æªè³Rust 1.50ï¼RoughTimeç±»åå ç¨8个åèï¼å¦å¾10-1æç¤ºã
å¾10-1 RoughTimeå¼å¨å
åä¸çåå¨
ä¸è¿ï¼Rust没æå¯¹æä¸¾çå¸å±ååºä¿è¯ï¼ä»¥ä¾¿ä¸ºæªæ¥çä¼åçåºç©ºé´ãå¨æäºæ åµä¸ï¼æä¸¾çå卿¹å¼å¯è½æ¯å¾ä¸æç¤ºçæ´é«æãä¾å¦ï¼ä¸äºæ³åç»æä½å¨å卿¶å¯ä»¥å®å ¨ä¸ä½¿ç¨æ ç¾ï¼æä»¬ç¨åä¼çå°ã
# ä½¿ç¨æä¸¾æå»ºä¸°å¯çæ°æ®ç»æ
æä¸¾å¨å¿«éå®ç°ç±»ä¼¼æ ç¶çæ°æ®ç»ææ¶ä¹å¾æç¨ãä¾å¦ï¼å设ä¸ä¸ªRustç¨åºéè¦å¤çä»»æçJSONæ°æ®ãå¨å åä¸ï¼ä»»ä½JSONææ¡£é½å¯ä»¥ç¨è¿ä¸ªRustç±»åç弿¥è¡¨ç¤ºï¼
use std::collections::HashMap;
enum Json {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<Json>),
Object(Box<HashMap<String, Json>>),
}
2
3
4
5
6
7
8
9
10
ç¨è±ææ¥è§£éè¿ä¸ªæ°æ®ç»æï¼ä¹å¾é¾æ¯Rustä»£ç æ¬èº«æ´æ¸
æ¥ãJSONæ åè§å®äºJSONææ¡£ä¸å¯è½åºç°çåç§æ°æ®ç±»åï¼nullãå¸å°å¼ãæ°åãå符串ãJSONå¼çæ°ç»ï¼ä»¥å带æå符串é®åJSONå¼ç对象ãJsonæä¸¾åªæ¯å°è¿äºç±»åå举äºåºæ¥ã
è¿ä¸æ¯ä¸ä¸ªå设çä¾åãå¨serde_jsonï¼ä¸ä¸ªç¨äºRustç»æä½çåºåååºï¼æ¯crates.ioä¸ä¸è½½éæé«çåºä¹ä¸ï¼ä¸ï¼å°±è½æ¾å°ä¸ä¸ªé常类似çæä¸¾ã
表示ObjectçHashMapå¤é¢çBoxåªæ¯ä¸ºäºè®©ææJson弿´ç´§åãå¨å
åä¸ï¼Jsonç±»åçå¼å ç¨å个æºå¨åé¿ãStringåVecå¼å ç¨ä¸ä¸ªæºå¨åé¿ï¼Rustè¿ä¼æ·»å ä¸ä¸ªæ ç¾åèãNullåå¸å°å¼çæ°æ®éä¸è¶³ä»¥å ç¨è¿ä¹å¤ç©ºé´ï¼ä½ææJsonå¼ç大å°å¿
é¡»ç¸åï¼å¤ä½ç空é´å°±è¢«é²ç½®äºãå¾10-2å±ç¤ºäºä¸äºJsonå¼å¨å
åä¸çå®é
åå¨ç¤ºä¾ã
å¾10-2 Jsonå¼å¨å
åä¸çåå¨
HashMapå ç¨çç©ºé´æ´å¤§ã妿æä»¬å¿
须卿¯ä¸ªJsonå¼ä¸ä¸ºå®é¢ç空é´ï¼é£ä¹Jsonå¼ä¼é常大ï¼å¤§çº¦å
«ä¸ªæºå¨åé¿ã使¯Box<HashMap>åªå ç¨ä¸ä¸ªæºå¨åé¿ï¼å®åªæ¯ä¸ä¸ªæåå ä¸åé
æ°æ®çæéã妿坹æ´å¤å段使ç¨Boxï¼æä»¬å¯ä»¥è®©Jsonç±»åæ´å ç´§åã
è¿éå¼å¾æ³¨æçæ¯ï¼è®¾ç½®è¿æ ·ä¸ä¸ªæ°æ®ç»ææ¯å¤ä¹å®¹æãå¨C++ä¸ï¼äººä»¬å¯è½ä¼ä¸ºæ¤ç¼åä¸ä¸ªç±»ï¼
class JSON {
private:
enum Tag {
Null, Boolean, Number, String, Array, Object
};
union Data {
bool boolean;
double number;
shared_ptr<string> str;
shared_ptr<vector<JSON>> array;
shared_ptr<unordered_map<string, JSON>> object;
Data() {}
~Data() {}
...
};
Tag tag;
Data data;
public:
bool is_null() const { return tag == Null; }
bool is_boolean() const { return tag == Boolean; }
bool get_boolean() const {
assert(is_boolean());
return data.boolean;
}
void set_boolean(bool value) {
this->~JSON(); // æ¸
çå符串/æ°ç»/对象å¼
tag = Boolean;
data.boolean = value;
}
...
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ä»
ä»
30è¡ä»£ç ï¼æä»¬ç工使åå¼å§ãè¿ä¸ªç±»è¿éè¦æé 彿°ãææå½æ°åèµå¼è¿ç®ç¬¦ãå¦ä¸ç§éæ©æ¯å建ä¸ä¸ªç±»å±æ¬¡ç»æï¼æä¸ä¸ªåºç±»JSONååç±»JSONBooleanãJSONStringççãä¸ç®¡åªç§æ¹å¼ï¼å®æåçC++ JSONåºé½ä¼æåå çè³æ´å¤çæ¹æ³ãå
¶ä»ç¨åºåè¦è±äºæ¶é´é
读æè½ç解并使ç¨å®ãèæ´ä¸ªRustæä¸¾åªç¨äºå
«è¡ä»£ç ã
# æ³åæä¸¾
æä¸¾å¯ä»¥æ¯æ³åçãæ ååºä¸çä¸¤ä¸ªç¤ºä¾æ¯Rustè¯è¨ä¸ä½¿ç¨æå¹¿æ³çæ°æ®ç±»åï¼
enum Option<T> {
None,
Some(T),
}
enum Result<T, E> {
Ok(T),
Err(E),
}
2
3
4
5
6
7
8
9
ç°å¨æä»¬å¯¹è¿äºç±»åå·²ç»è¶³å¤çæäºï¼æ³åæä¸¾çè¯æ³åæ³åç»æä½çè¯æ³æ¯ä¸æ ·çã
æä¸ä¸ªä¸å¤ªææ¾çç»èæ¯ï¼å½ç±»åTæ¯å¼ç¨ãBoxæå
¶ä»æºè½æéç±»åæ¶ï¼Rustå¯ä»¥çç¥Option<T>çæ ç¾å段ãç±äºè¿äºæéç±»åé½ä¸å
许为é¶ï¼æä»¥Rustå¯ä»¥ç¨ä¸ä¸ªæºå¨åé¿æ¥è¡¨ç¤ºOption<Box<i32>>ï¼ä¾å¦ï¼ç¨0表示Noneï¼ç¨éé¶å¼è¡¨ç¤ºSomeæéãè¿ä½¿å¾è¿ç§Optionç±»åä¸CæC++ä¸å¯è½ä¸ºnullçæéå¼é常ç¸ä¼¼ãä¸åä¹å¤å¨äºï¼Rustçç±»åç³»ç»è¦æ±ä½ å¨ä½¿ç¨Optionçå
容ä¹åï¼å¿
é¡»æ£æ¥å®æ¯å¦ä¸ºSomeãè¿ææå°é¿å
äºç©ºæéè§£å¼ç¨çé®é¢ã
åªç¨å è¡ä»£ç å°±è½æå»ºæ³åæ°æ®ç»æï¼
// ä¸ä¸ªæåºçTç±»åå
ç´ éåã
enum BinaryTree<T> {
Empty,
NonEmpty(Box<TreeNode<T>>),
}
// BinaryTreeçä¸é¨åã
struct TreeNode<T> {
element: T,
left: BinaryTree<T>,
right: BinaryTree<T>,
}
2
3
4
5
6
7
8
9
10
11
12
è¿å è¡ä»£ç å®ä¹äºä¸ä¸ªBinaryTreeç±»åï¼å®å¯ä»¥åå¨ä»»ææ°éçTç±»åçå¼ã
è¿ä¸¤ä¸ªå®ä¹ä¸è´å«äºå¤§éä¿¡æ¯ï¼æä»¥æä»¬è±ç¹æ¶é´éåéå¥å°æä»£ç ç¿»è¯æè±æãæ¯ä¸ªBinaryTreeå¼è¦ä¹æ¯Emptyï¼è¦ä¹æ¯NonEmptyã妿æ¯Emptyï¼é£ä¹å®æ ¹æ¬ä¸å
嫿°æ®ã妿æ¯NonEmptyï¼é£ä¹å®æä¸ä¸ªBoxï¼è¿æ¯ä¸ä¸ªæåå ä¸åé
çTreeNodeçæéã
æ¯ä¸ªTreeNodeå¼å
å«ä¸ä¸ªå®é
çå
ç´ ï¼ä»¥åå¦å¤ä¸¤ä¸ªBinaryTreeå¼ãè¿æå³ç䏿£µæ å¯ä»¥å
å«åæ ï¼å æ¤ä¸ä¸ªNonEmptyæ å¯ä»¥æä»»ææ°éçå代ã
å¾10-3å±ç¤ºäºä¸ä¸ªBinaryTree<&str>ç±»åå¼ç示æå¾ãåOption<Box<T>>䏿 ·ï¼Rustçç¥äºæ ç¾åæ®µï¼æä»¥ä¸ä¸ªBinaryTreeå¼åªå ç¨ä¸ä¸ªæºå¨åé¿ã
å¾10-3 å
å«å
个å符串çBinaryTree
å¨è¿ä¸ªæ ä¸æå»ºä»»ä½ä¸ä¸ªç¹å®çèç¹é½å¾ç®åï¼
use self::BinaryTree::*;
let jupiter_tree = NonEmpty(Box::new(TreeNode {
element: "Jupiter",
left: Empty,
right: Empty,
}));
2
3
4
5
6
7
æ´å¤§çæ å¯ä»¥ç±è¾å°çæ æå»ºèæï¼
let mars_tree = NonEmpty(Box::new(TreeNode {
element: "Mars",
left: jupiter_tree,
right: mercury_tree,
}));
2
3
4
5
èªç¶å°ï¼è¿ä¸ªèµå¼æä½å°jupiter_nodeåmercury_nodeçæææè½¬ç§»å°äºå®ä»¬çæ°ç¶èç¹ã
æ çå ¶ä½é¨åéµå¾ªç¸åçæ¨¡å¼ãæ ¹èç¹ä¸å ¶ä»èç¹æ²¡æåºå«ï¼
let tree = NonEmpty(Box::new(TreeNode {
element: "Saturn",
left: mars_tree,
right: uranus_tree,
}));
2
3
4
5
卿¬ç« åé¢ï¼æä»¬å°å±ç¤ºå¦ä½å¨BinaryTreeç±»åä¸å®ç°ä¸ä¸ªaddæ¹æ³ï¼è¿æ ·æä»¬å°±å¯ä»¥è¿æ ·åï¼
let mut tree = BinaryTree::Empty;
for planet in planets {
tree.add(planet);
}
2
3
4
æ è®ºä½ ä¹å使ç¨åªç§è¯è¨ï¼å¨Rustä¸å建åBinaryTreeè¿æ ·çæ°æ®ç»æå¯è½é½éè¦ä¸äºç»ä¹ ãä¸å¼å§ï¼ä½ å¯è½ä¸å¤ªæ¸
æ¥Boxåºè¯¥æ¾å¨åªéãä¸ç§æ¾å°å¯è¡è®¾è®¡çæ¹æ³æ¯ç»ä¸å¼ 类似å¾10-3çå¾ï¼å±ç¤ºä½ å¸ææ°æ®å¨å
åä¸çå¸å±ãç¶åä»å¾å忍坼åºä»£ç ãæ¯ä¸ªç©å½¢éå代表ä¸ä¸ªç»æä½æå
ç»ï¼æ¯ä¸ªç®å¤´ä»£è¡¨ä¸ä¸ªBoxæå
¶ä»æºè½æéã弿¸
æ¥æ¯ä¸ªå段çç±»åæç¹åè§£è°ï¼ä½è¿æ¯å¯ä»¥è§£å³çãè§£å¼è¿ä¸ªè°é¢ç忥æ¯è½å¤æ§å¶ç¨åºçå
å使ç¨ã
ç°å¨æ¥è¯´è¯´æä»¬å¨å¼è¨ä¸æå°ç â代价âãæä¸¾çæ ç¾å段ä¼å ç¨ä¸ç¹å åï¼å¨æåçæ åµä¸æå¤å ç¨å «ä¸ªåèï¼ä½é常è¿å¯ä»¥å¿½ç¥ä¸è®¡ãæä¸¾çæ£ç缺ç¹ï¼å¦æå¯ä»¥è¿ä¹è¯´çè¯ï¼æ¯ï¼Rust代ç ä¸è½éæå°è¯è®¿é®å段ï¼èä¸ç®¡è¿äºå段å¨å¼ä¸æ¯å¦å®é åå¨ï¼
let r = shape.radius; // é误ï¼Shapeç±»åæ²¡æradiusåæ®µ
è®¿é®æä¸¾ä¸æ°æ®çå¯ä¸å®å ¨æ¹å¼æ¯ä½¿ç¨æ¨¡å¼ã
# 模å¼
åæ³ä¸ä¸æ¬ç« åé¢å®ä¹çRoughTimeç±»åï¼
enum RoughTime {
InThePast(TimeUnit, u32),
JustNow,
InTheFuture(TimeUnit, u32),
}
2
3
4
5
åè®¾ä½ æä¸ä¸ªRoughTimeå¼ï¼æ³è¦å¨ç½é¡µä¸æ¾ç¤ºå®ãä½ éè¦è®¿é®è¿ä¸ªå¼éé¢çTimeUnitåu32åæ®µãRustä¸å
è®¸ä½ ç´æ¥éè¿rough_time.0årough_time.1æ¥è®¿é®å®ä»¬ï¼å 为æ¯ç«è¿ä¸ªå¼å¯è½æ¯RoughTime::JustNowï¼å®æ²¡æå段ãé£ä¹ï¼ä½ è¦å¦ä½è·åè¿äºæ°æ®å¢ï¼
ä½ éè¦ä½¿ç¨match表达å¼ï¼
fn rough_time_to_english(rt: RoughTime) -> String {
match rt {
RoughTime::InThePast(units, count) =>
format!("{} {} ago", count, units.plural()),
RoughTime::JustNow =>
format!("just now"),
RoughTime::InTheFuture(units, count) =>
format!("{} {} from now", count, units.plural()),
}
}
2
3
4
5
6
7
8
9
10
matchæ§è¡æ¨¡å¼å¹é
ï¼å¨è¿ä¸ªä¾åä¸ï¼æ¨¡å¼æ¯åºç°å¨ç¬¬3ã5ã7è¡=>符å·ä¹åçé¨åãå¹é
RoughTimeå¼ç模å¼çèµ·æ¥å°±åç¨äºå建RoughTimeå¼ç表达å¼ï¼è¿å¹¶éå·§åã表达å¼äº§çå¼ï¼æ¨¡å¼æ¶è´¹å¼ï¼äºè
使ç¨äºå¾å¤ç¸åçè¯æ³ã
让æä»¬éæ¥åæè¿ä¸ªmatch表达å¼è¿è¡æ¶ä¼åçä»ä¹ãå设rtç弿¯RoughTime::InTheFuture(TimeUnit::Months, 1)ãRusté¦å
å°è¯å°è¿ä¸ªå¼ä¸ç¬¬3è¡ç模å¼è¿è¡å¹é
ãå¦å¾10-4æç¤ºï¼å®ä»¬ä¸å¹é
ã
å¾10-4 ä¸ä¸ªä¸å¹é
çRoughTimeå¼å模å¼
对æä¸¾ãç»æä½æå ç»è¿è¡æ¨¡å¼å¹é æ¶ï¼å°±å¥½åRustå¨è¿è¡ä»å·¦å°å³çç®åæ«æï¼æ£æ¥æ¨¡å¼çæ¯ä¸ªç»ä»¶ï¼ç弿¯å¦ä¸ä¹å¹é ã妿ä¸å¹é ï¼Rustå°±ä¼ç»§ç»å°è¯ä¸ä¸ä¸ªæ¨¡å¼ã
第3è¡å第5è¡ç模å¼é½å¹é
失败ï¼ä½ç¬¬7è¡ç模å¼å¹é
æåï¼å¾10-5ï¼ã
å¾10-5 å¹é
æå
å½ä¸ä¸ªæ¨¡å¼å
å«åunitsåcountè¿æ ·çç®åæ è¯ç¬¦æ¶ï¼è¿äºæ è¯ç¬¦ä¼å¨æ¨¡å¼åé¢ç代ç ä¸æä¸ºå±é¨åéãå¼ä¸çç¸åºå
容ä¼è¢«å¤å¶æç§»å¨å°è¿äºæ°åéä¸ãRustå°TimeUnit::Monthsåå¨å°unitsä¸ï¼å°1åå¨å°countä¸ï¼æ§è¡ç¬¬8è¡ä»£ç ï¼å¹¶è¿åå符串"1 months from now"ã
è¿ä¸ªè¾åºåå¨ä¸ä¸ªå°è¯æ³é®é¢ï¼å¯ä»¥éè¿å¨match䏿·»å å¦ä¸ä¸ªåæ¯æ¥ä¿®å¤ï¼
RoughTime::InTheFuture(unit, 1) =>
format!("a {} from now", unit.singular()),
2
è¿ä¸ªåæ¯åªæå¨countåæ®µæ°å¥½ä¸º1æ¶æä¼å¹é
ãæ³¨æï¼è¿æ®µæ°ä»£ç å¿
须添å å¨ç¬¬7è¡ä¹åã妿æä»¬æå®æ·»å 卿åï¼Rustæ°¸è¿ä¸ä¼æ§è¡å°å®ï¼å 为第7è¡ç模å¼ä¼å¹é
ææInTheFutureå¼ãå¦æä½ ç¯äºè¿ç§é误ï¼Rustç¼è¯å¨ä¼ååº âä¸å¯è¾¾æ¨¡å¼â çè¦å ã
å³ä½¿æ·»å äºæ°ä»£ç ï¼RoughTime::InTheFuture(TimeUnit::Hours, 1)ä»ç¶åå¨é®é¢ï¼ç»æ"a hour from now"ä¸å¤ªæ£ç¡®ï¼è¿å°±æ¯è±è¯çç¹ç¹ãè¿ä¸ªé®é¢ä¹å¯ä»¥éè¿å¨matchä¸åæ·»å ä¸ä¸ªåæ¯æ¥è§£å³ã
è¿ä¸ªä¾å表æï¼æ¨¡å¼å¹é
䏿䏾é
åå¾å¾å¥½ï¼çè³å¯ä»¥æµè¯æä¸¾ä¸å
å«çæ°æ®ï¼è¿ä½¿å¾matchæä¸ºCè¯è¨ä¸switchè¯å¥ç强大ãçµæ´»çæ¿ä»£æ¹æ¡ã
å°ç®å为æ¢ï¼æä»¬åªçå°äºå¹é æä¸¾å¼ç模å¼ãå®é ä¸ä¸æ¢å¦æ¤ãRustæ¨¡å¼æä¸å¥èªå·±çè§åï¼æ»ç»å¨è¡¨10-1ä¸ãæ¬ç« çå©ä½é¨å大é¨åå 容å°å´ç»è¡¨ä¸å±ç¤ºçç¹æ§å±å¼ã 表10-1 模å¼
| 模å¼ç±»å | ç¤ºä¾ | 注é |
|---|---|---|
| åé¢é | 100"name" | å¹é ç¡®åçå¼ï¼ä¹å 许使ç¨å¸¸éå |
| èå´ | 0..=100'a'..='k' | å¹é èå´å çä»»ä½å¼ï¼å æ¬è¾¹çå¼ |
| éé 符åé | _ | å¹é ä»»ä½å¼å¹¶å¿½ç¥å® |
| åé | name | å_类似ï¼ä½ä¼å°å¼ç§»å¨æå¤å¶å°ä¸ä¸ªæ°çå±é¨åéä¸ |
| å¯åç»å®åé | mut count | ç»å®ä¸ä¸ªå¯åå¼ç¨ï¼è䏿¯ç§»å¨æå¤å¶å¼ |
| 带å¼ç¨çæ¨¡å¼ | ref fieldref mut field | åç¨å¹é å¼çå¼ç¨ï¼è䏿¯ç§»å¨æå¤å¶å® |
| 带ç»å®ç忍¡å¼ | val @ 0..=99ref circle @ Shape::Circle { .. } | 使ç¨@左边çåéåå¹é
å³è¾¹çæ¨¡å¼ |
| æä¸¾æ¨¡å¼ | Some(value)NonePet::Orca | å¹é æä¸¾å¼ |
| å ç»æ¨¡å¼ | (key, value)(r, g, b) | å¹é å ç» |
| æ°ç»æ¨¡å¼ | [a, b, c, d, e, f, g][first, second][first, _, third][first, .., nth][] | å¹é æ°ç» |
| åçæ¨¡å¼ | [first, second][first, _, third][first, .., nth][] | å¹é åç |
| ç»æä½æ¨¡å¼ | Color(r, g, b)Point { x, y }Card { suit: Clubs, rank: n }Account { id, name, .. } | å¹é ç»æä½ |
| å¼ç¨æ¨¡å¼ | &value&(k, v) | ä» å¹é å¼ç¨å¼ |
| å¤éæ¨¡å¼ | 'a' | 'A' | ä»
å¨å¯å驳模å¼ä¸ææï¼matchãif letãwhile letï¼ |
| å®å«è¡¨è¾¾å¼ | x if x * x <= r2 | ä»
å¨match䏿æï¼å¨letç䏿 æï¼ |
# 模å¼ä¸çåé¢éãåéåéé 符
å°ç®å为æ¢ï¼æä»¬å±ç¤ºäºmatch表达å¼ä¸æä¸¾çé
å使ç¨ãå
¶ä»ç±»åä¹å¯ä»¥è¿è¡å¹é
ãå½ä½ éè¦ç±»ä¼¼Cè¯è¨ä¸switchè¯å¥çåè½æ¶ï¼å¯ä»¥å¯¹æ´æ°å¼ä½¿ç¨matchãå0å1è¿æ ·çæ´æ°åé¢éå¯ä»¥ä½ä¸ºæ¨¡å¼ï¼
match meadow.count_rabbits() {
0 => {}, // 没ä»ä¹å¯è¯´ç
1 => println!("A rabbit is nosing around in the clover."),
n => println!("There are {} rabbits hopping about in the meadow", n),
}
2
3
4
5
妿èå°ä¸æ²¡æå
åï¼æ¨¡å¼0å°±ä¼å¹é
ãå¦æåªæä¸åªå
åï¼1ä¼å¹é
ã妿æä¸¤åªææ´å¤å
åï¼å°±ä¼å¹é
å°ç¬¬ä¸ä¸ªæ¨¡å¼nãè¿ä¸ªæ¨¡å¼åªæ¯ä¸ä¸ªåéåï¼å®å¯ä»¥å¹é
ä»»ä½å¼ï¼å¹¶ä¸å¹é
çå¼ä¼è¢«ç§»å¨æå¤å¶å°ä¸ä¸ªæ°çå±é¨åéä¸ãæä»¥å¨è¿ä¸ªä¾åä¸ï¼meadow.count_rabbits()çå¼è¢«åå¨å¨æ°çå±é¨åénä¸ï¼ç¶åæä»¬æå°è¿ä¸ªåéã
å ¶ä»åé¢éä¹å¯ä»¥ç¨ä½æ¨¡å¼ï¼å æ¬å¸å°å¼ãå符ï¼çè³å符串ï¼
let calendar = match settings.get_string("calendar") {
"gregorian" => Calendar::Gregorian,
"chinese" => Calendar::Chinese,
"ethiopian" => Calendar::Ethiopian,
other => return parse_error("calendar", other),
};
2
3
4
5
6
å¨è¿ä¸ªä¾åä¸ï¼otheråä¸ä¸ä¸ªä¾åä¸çn䏿 ·ï¼ç¨ä½éé
模å¼ãè¿äºæ¨¡å¼åswitchè¯å¥ä¸çdefaultæ
åµèµ·çç¸åçä½ç¨ï¼å¹é
é£äºä¸å
¶ä»æ¨¡å¼é½ä¸å¹é
çå¼ã
å¦æä½ éè¦ä¸ä¸ªéé
模å¼ï¼ä½åä¸å
³å¿å¹é
å°çå¼ï¼å¯ä»¥ä½¿ç¨å个ä¸å线_ä½ä¸ºæ¨¡å¼ï¼å³éé
符模å¼ï¼
let caption = match photo.tagged_pet() {
Pet::Tyrannosaur => "RRRAAAAAHHHHHH",
Pet::Samoyed => "*dog thoughts*",
_ => "I'm cute, love me", // éç¨ç说ææåï¼éç¨äºä»»ä½å® ç©
};
2
3
4
5
éé
符模å¼å¹é
ä»»ä½å¼ï¼ä½ä¸ä¼å°å
¶åå¨å¨ä»»ä½å°æ¹ãç±äºRustè¦æ±æ¯ä¸ªmatch表达å¼é½å¤çææå¯è½çå¼ï¼æä»¥é叏卿«å°¾éè¦ä¸ä¸ªéé
符ãå³ä½¿ä½ é常确å®å©ä½çæ
åµä¸ä¼åçï¼ä¹è³å°å¿
须添å ä¸ä¸ªå¤ç¨åæ¯ï¼ä¹è®¸æ¯ä¸ä¸ªä¼è§¦åpanicç忝ï¼
// æå¾å¤ç§Shapeï¼ä½æä»¬åªæ¯æâéæ©âææ¬æç©å½¢åºåå
çææå
容ã
// ä½ ä¸è½éæ©æ¤åææ¢¯å½¢ã
match document.selection() {
Shape::TextSpan(start, end) => paint_text_selection(start, end),
Shape::Rectangle(rect) => paint_rect_selection(rect),
_ => panic!("unexpected selection type"),
}
2
3
4
5
6
7
# å ç»æ¨¡å¼åç»æä½æ¨¡å¼
å ç»æ¨¡å¼ç¨äºå¹é å ç»ãå½ä½ æ³å¨ä¸æ¬¡å¹é ä¸è·åå¤ä¸ªæ°æ®æ¶ï¼å®ä»¬é常æç¨ï¼
fn describe_point(x: i32, y: i32) -> &'static str {
use std::cmp::Ordering::*;
match (x.cmp(&0), y.cmp(&0)) {
(Equal, Equal) => "at the origin",
(_, Equal) => "on the x axis",
(Equal, _) => "on the y axis",
(Greater, Greater) => "in the first quadrant",
(Less, Greater) => "in the second quadrant",
_ => "somewhere else",
}
}
2
3
4
5
6
7
8
9
10
11
ç»æä½æ¨¡å¼åç»æä½è¡¨è¾¾å¼ä¸æ ·ï¼ä½¿ç¨è±æ¬å·ãå®ä»¬ä¸ºæ¯ä¸ªå段å å«ä¸ä¸ªå模å¼ï¼
match balloon.location {
Point { x: 0, y: height } =>
println!("straight up {} meters", height),
Point { x: x, y: y } =>
println!("at ({}m, {}m)", x, y),
}
2
3
4
5
6
å¨è¿ä¸ªä¾åä¸ï¼å¦æç¬¬ä¸ä¸ªåæ¯å¹é
ï¼é£ä¹balloon.location.yä¼è¢«åå¨å°æ°çå±é¨åéheightä¸ã
å设balloon.locationæ¯Point { x: 30, y: 40 }ãåå¾å¸¸ä¸æ ·ï¼Rustä¼ä¾æ¬¡æ£æ¥æ¯ä¸ªæ¨¡å¼çæ¯ä¸ªç»ä»¶ï¼å¾10-6ï¼ã
å¾10-6 ç»æä½ç模å¼å¹é
第äºä¸ªåæ¯å¹é
ï¼æä»¥è¾åºä¼æ¯at (30m, 40m)ã
åPoint { x: x, y: y }è¿æ ·ç模å¼å¨å¹é
ç»æä½æ¶å¾å¸¸è§ï¼éå¤çååä¼é æè§è§å¹²æ°ï¼æä»¥Rustä¸ºæ¤æä¾äºä¸ç§ç®åå½¢å¼ï¼Point {x, y}ï¼å«ä¹æ¯ä¸æ ·çãè¿ä¸ªæ¨¡å¼ä»ç¶ä¼å°ç¹çxåæ®µåå¨å°æ°çå±é¨åéxä¸ï¼å°yåæ®µåå¨å°æ°çå±é¨åéyä¸ã
å³ä½¿ä½¿ç¨äºç®åå½¢å¼ï¼å½æä»¬åªå ³å¿å¤§åç»æä½çå ä¸ªåæ®µæ¶ï¼å¹é å®ä»ç¶å¾éº»ç¦ï¼
match get_account(id) {
...
Some(Account {
name, language, // <- - - æä»¬å
³å¿ç2ä¸ªåæ®µ
id: _, status: _, address: _, birthday: _, eye_color: _,
pet: _, security_question: _, hashed_innermost_secret: _,
is_adamantium_preferred_customer: _,
}) =>
language.show_custom_greeting(name),
}
2
3
4
5
6
7
8
9
10
为äºé¿å
è¿ç§æ
åµï¼å¯ä»¥ä½¿ç¨..åè¯Rustä½ ä¸å
³å¿å
¶ä»ä»»ä½å段ï¼
Some(Account { name, language, .. }) =>
language.show_custom_greeting(name),
2
# æ°ç»æ¨¡å¼ååçæ¨¡å¼
æ°ç»æ¨¡å¼ç¨äºå¹é æ°ç»ãå®ä»¬å¸¸è¢«ç¨æ¥çéåºä¸äºç¹æ®æ åµçå¼ï¼å¹¶ä¸å¨å¤çé£äºå¼çå«ä¹å ä½ç½®èå¼çæ°ç»æ¶é常æç¨ã
ä¾å¦ï¼å¨å°è²è°ã饱å度å亮度ï¼HSLï¼é¢è²å¼è½¬æ¢ä¸ºçº¢ã绿ãèï¼RGBï¼é¢è²å¼æ¶ï¼äº®åº¦ä¸ºé¶æå
¨äº®åº¦çé¢è²å嫿¯é»è²æç½è²ãæä»¬å¯ä»¥ä½¿ç¨match表达å¼è½»æ¾å¤çè¿äºæ
åµã
fn hsl_to_rgb(hsl: [u8; 3]) -> [u8; 3] {
match hsl {
[_, _, 0] => [0, 0, 0],
[_, _, 255] => [255, 255, 255],
...
}
}
2
3
4
5
6
7
åçæ¨¡å¼ä¸ä¹ç±»ä¼¼ï¼ä½ä¸æ°ç»ä¸åï¼åççé¿åº¦æ¯å¯åçï¼æä»¥åçæ¨¡å¼ä¸ä»
伿 ¹æ®å¼è¿è¡å¹é
ï¼è¿ä¼æ ¹æ®é¿åº¦è¿è¡å¹é
ãåçæ¨¡å¼ä¸ç..å¯ä»¥å¹é
ä»»ææ°éçå
ç´ ï¼
fn greet_people(names: &[&str]) {
match names {
[] => { println!("Hello, nobody.") },
[a] => { println!("Hello, {}.", a) },
[a, b] => { println!("Hello, {} and {}.", a, b) },
[a, .., b] => { println!("Hello, everyone from {} to {}.", a, b) }
}
}
2
3
4
5
6
7
8
# å¼ç¨æ¨¡å¼
Rustæ¨¡å¼æ¯æä¸¤ç§å¤çå¼ç¨çç¹æ§ãref模å¼ç¨äºåç¨å¹é
å¼çä¸é¨åï¼&模å¼ç¨äºå¹é
å¼ç¨ãæä»¬å
ä»ç»ref模å¼ã
å¹é ä¸ä¸ªä¸å¯å¤å¶çå¼ä¼ç§»å¨è¯¥å¼ãç»§ç»ä»¥è´¦æ·ä¸ºä¾ï¼è¿æ®µä»£ç æ¯æ æçï¼
match account {
Account { name, language, .. } => {
ui.greet(&name, &language);
ui.show_settings(&account); // é误: åç¨äºå·²ç§»å¨çå¼: `account`
}
}
2
3
4
5
6
å¨è¿éï¼account.nameåaccount.languageåæ®µè¢«ç§»å¨å°äºå±é¨åénameålanguageä¸ï¼accountçå
¶ä½é¨å被丢å¼ãè¿å°±æ¯ä¸ºä»ä¹æä»¬ä¹åä¸è½ååç¨å®çå¼ç¨ã
妿nameålanguage齿¯å¯å¤å¶çå¼ï¼Rustä¼å¤å¶è¿äºå段è䏿¯ç§»å¨å®ä»¬ï¼è¿æ ·ä»£ç 就没é®é¢äºãä½å设å®ä»¬æ¯Stringç±»åï¼æä»¬è¯¥æä¹åå¢ï¼
æä»¬éè¦ä¸ç§æ¨¡å¼ï¼å®åç¨å¹é
çå¼è䏿¯ç§»å¨å®ä»¬ãrefå
³é®åå°±è½åå°è¿ä¸ç¹ï¼
match account {
Account { ref name, ref language, .. } => {
ui.greet(name, language);
ui.show_settings(&account); // 没é®é¢
}
}
2
3
4
5
6
ç°å¨ï¼å±é¨åénameålanguageæ¯æåaccountä¸ç¸åºå段çå¼ç¨ãç±äºaccountåªæ¯è¢«åç¨ï¼è䏿¯è¢«æ¶èï¼æä»¥ç»§ç»å¯¹å®è°ç¨æ¹æ³æ¯å¯è¡çã
ä½ å¯ä»¥ä½¿ç¨ref mutæ¥åç¨å¯åå¼ç¨ï¼
match line_result {
Err(ref err) => log_error(err), // `err` æ¯ &Error (å
±äº«å¼ç¨)
Ok(ref mut line) => { // `line` æ¯ &mut String (å¯åå¼ç¨)
trim_comments(line); // å°±å°ä¿®æ¹ String
handle(line);
}
}
2
3
4
5
6
7
模å¼Ok(ref mut line)å¹é
任使åçç»æï¼å¹¶åç¨å
¶ä¸åå¨çæåå¼çå¯åå¼ç¨ã
å¦ä¸ç§å¼ç¨æ¨¡å¼æ¯&模å¼ã以&å¼å¤´ç模å¼å¹é
å¼ç¨ï¼
match sphere.center() {
&Point3d { x, y, z } => ...
}
2
3
å¨è¿ä¸ªä¾åä¸ï¼å设sphere.center()è¿åä¸ä¸ªæåsphereç§æåæ®µçå¼ç¨ï¼è¿å¨Rust䏿¯ä¸ç§å¸¸è§ç模å¼ãè¿åç弿¯ä¸ä¸ªPoint3dçå°åã妿ä¸å¿å¨åç¹ï¼é£ä¹sphere.center()è¿å&Point3d { x: 0.0, y: 0.0, z: 0.0 }ã
模å¼å¹é
çè¿ç¨å¦å¾10-7æç¤ºã
å¾10-7 å¼ç¨ç模å¼å¹é
è¿æç¹æ£æï¼å 为Rustå¨è¿éæ¯å¨è§£å¼ç¨ï¼èæä»¬é常å°è¿ç§æä½ä¸*è¿ç®ç¬¦è系起æ¥ï¼è䏿¯&è¿ç®ç¬¦ãè¦è®°ä½çæ¯ï¼æ¨¡å¼åè¡¨è¾¾å¼æ¯ç¸åçã表达å¼(x, y)å°ä¸¤ä¸ªå¼ç»åæä¸ä¸ªæ°çå
ç»ï¼è模å¼(x, y)åç¸åï¼å®å¹é
ä¸ä¸ªå
ç»å¹¶åè§£åºä¸¤ä¸ªå¼ã&乿¯å¦æ¤ãå¨è¡¨è¾¾å¼ä¸ï¼&å建ä¸ä¸ªå¼ç¨ã卿¨¡å¼ä¸ï¼&å¹é
ä¸ä¸ªå¼ç¨ã
å¹é
å¼ç¨éµå¾ªæä»¬æçç¥çææè§åãçå½å¨æä¼è¢«å¼ºå¶æ§è¡ãä½ ä¸è½éè¿å
±äº«å¼ç¨è·å¾å¯åè®¿é®æéãèä¸ï¼å³ä½¿æ¯å¯åå¼ç¨ï¼ä½ ä¹ä¸è½ä»å¼ç¨ä¸ç§»åºå¼ã彿们å¹é
&Point3d { x, y, z }æ¶ï¼åéxãyåzä¼å¾å°åæ ç坿¬ï¼èåå§çPoint3då¼ä¿æä¸åãè¿ä¹æä»¥å¯è¡ï¼æ¯å 为è¿äºå段æ¯å¯å¤å¶çã妿æä»¬å¯¹ä¸ä¸ªå段ä¸å¯å¤å¶çç»æä½å°è¯åæ ·çæä½ï¼å°±ä¼å¾å°ä¸ä¸ªé误ï¼
match friend.borrow_car() {
Some(&Car { engine, .. }) => // é误: ä¸è½ä»åç¨ä¸ç§»åºå¼
...
None => {}
}
2
3
4
5
æè§£åæ¥ç汽车å½é¶ä»¶ä¸å¤ªåéï¼Rustä¹ä¸å
è®¸è¿æ ·åãä½ å¯ä»¥ä½¿ç¨ref模å¼åç¨å¯¹æä¸ªé¨åçå¼ç¨ï¼ä½ä½ 并䏿¥æå®ï¼
Some(&Car { ref engine, .. }) => // 没é®é¢ï¼engineæ¯ä¸ä¸ªå¼ç¨
æä»¬åæ¥çä¸ä¸ª&模å¼çä¾åãå设æä»¬æä¸ä¸ªè¿ä»£å¨charsï¼ç¨äºéåå符串ä¸çå符ï¼å¹¶ä¸å®æä¸ä¸ªæ¹æ³chars.peek()ï¼è¯¥æ¹æ³è¿åä¸ä¸ªOption<&char>ï¼å¦ææä¸ä¸ä¸ªå符ï¼åè¿å对å®çå¼ç¨ï¼å®é
ä¸ï¼å¯çª¥è§çè¿ä»£å¨ç¡®å®ä¼è¿åä¸ä¸ªOption<&ItemType>ï¼æä»¬å°å¨ç¬¬15ç« çå°ï¼ã
ç¨åºå¯ä»¥ä½¿ç¨&æ¨¡å¼æ¥è·åæåçå符ï¼
match chars.peek() {
Some(&c) => println!("coming up: {:?}", c),
None => println!("end of chars"),
}
2
3
4
# å¹é å®å«
ææ¶ï¼match忝å¨è¢«è§ä¸ºå¹é
ä¹åï¼è¿å¿
须满足å
¶ä»æ¡ä»¶ãå设æä»¬æ£å¨å®ç°ä¸ä¸ªæå
è¾¹å½¢æ ¼åçæ£çæ¸¸æï¼ç©å®¶ååç¹å»ä»¥ç§»å¨æ£åã为äºç¡®è®¤ç¹å»ææï¼æä»¬å¯è½ä¼å°è¯è¿æ ·åï¼
fn check_move(current_hex: Hex, click: Point) -> game::Result<Hex> {
match point_to_hex(click) {
None =>
Err("That's not a game space."),
Some(current_hex) => // å¦æç¨æ·ç¹å»äºå½åçå
è¾¹å½¢æ ¼åï¼å°è¯å¹é
ï¼ä½è¿ä¸èµ·ä½ç¨ï¼è§ä¸é¢çè§£éï¼
Err("You are already there! You must click somewhere else."),
Some(other_hex) =>
Ok(other_hex)
}
}
2
3
4
5
6
7
8
9
10
è¿æ®µä»£ç ä¼å¤±è´¥ï¼å 为模å¼ä¸çæ è¯ç¬¦ä¼å¼å
¥æ°çåéãè¿éçæ¨¡å¼Some(current_hex)å建äºä¸ä¸ªæ°çå±é¨åécurrent_hexï¼é®è½äºåæ°current_hexãRustä¼å¯¹æ¤ä»£ç ååºå 个è¦åââç¹å«æ¯ï¼matchçæåä¸ä¸ªåæ¯æ¯ä¸å¯è¾¾çã
ä¸ç§ä¿®å¤æ¹æ³æ¯å¨match忝ä¸ç®åå°ä½¿ç¨if表达å¼ï¼
match point_to_hex(click) {
None => Err("That's not a game space."),
Some(hex) => {
if hex == current_hex {
Err("You are already there! You must click somewhere else")
} else {
Ok(hex)
}
}
}
2
3
4
5
6
7
8
9
10
ä¸è¿ï¼Rustè¿æä¾äºå¹é
å®å«ï¼match guardsï¼ï¼å³ä¸ä¸ªmatch忝è¦åºç¨å¿
须满足çé¢å¤æ¡ä»¶ï¼å卿¨¡å¼å忝ç=>符å·ä¹é´ï¼æ ¼å¼ä¸ºif CONDITIONï¼
match point_to_hex(click) {
None => Err("That's not a game space."),
Some(hex) if hex == current_hex =>
Err("You are already there! You must click somewhere else"),
Some(hex) => Ok(hex)
}
2
3
4
5
6
å¦ææ¨¡å¼å¹é ï¼ä½æ¡ä»¶ä¸ºåï¼åç»§ç»å¹é ä¸ä¸ä¸ªåæ¯ã
# å¹é å¤ç§å¯è½æ§
ç«çº¿ï¼|ï¼å¯ä»¥ç¨äºå¨å个match忝ä¸ç»åå¤ä¸ªæ¨¡å¼ï¼
let at_end = match chars.peek() {
Some(&'\r') | Some(&'\n') | None => true,
_ => false,
};
2
3
4
å¨è¡¨è¾¾å¼ä¸ï¼|æ¯æä½æè¿ç®ç¬¦ï¼ä½å¨è¿éï¼å®çä½ç¨æ´åæ¯æ£å表达å¼ä¸ç|符å·ã
妿chars.peek()å¹é
è¿ä¸ä¸ªæ¨¡å¼ä¸çä»»ä½ä¸ä¸ªï¼at_endå°±ä¼è¢«è®¾ç½®ä¸ºtrueã
使ç¨..=æ¥å¹é
䏿´ä¸ªèå´çå¼ãèå´æ¨¡å¼å
æ¬èµ·å§å¼åç»æå¼ï¼æä»¥'0'..='9'å¹é
ææASCIIæ°åï¼
match next_char {
'0'..='9' => self.read_number(),
'a'..='z' | 'A'..='Z' => self.read_word(),
' ' | '\t' | '\n' => self.skip_whitespace(),
_ => self.handle_punctuation(),
}
2
3
4
5
6
Rustï¼ç®åï¼ä¸å
è®¸å¨æ¨¡å¼ä¸ä½¿ç¨ä¸å
å«ç»æå¼çèå´ï¼å¦0..100ã
# 带@çæ¨¡å¼ç»å®
æåï¼x @ patternçå¹é
æ¹å¼ä¸ç»å®ç模å¼å®å
¨ç¸åï¼ä½å¹é
æåæ¶ï¼å®ä¸ä¼ä¸ºå¹é
å¼çå个é¨åå建åéï¼èæ¯å建ä¸ä¸ªåç¬çåéxï¼å¹¶å°æ´ä¸ªå¼ç§»å¨æå¤å¶å°å
¶ä¸ãä¾å¦ï¼åè®¾ä½ æè¿æ ·ä¸æ®µä»£ç ï¼
match self.get_selection() {
Shape::Rect(top_left, bottom_right) => {
optimized_paint(&Shape::Rect(top_left, bottom_right))
}
other_shape => {
paint_outline(other_shape.get_outline())
}
}
2
3
4
5
6
7
8
注æï¼ç¬¬ä¸ç§æ
åµè§£å
äºä¸ä¸ªShape::Rectå¼ï¼å´å¨ä¸ä¸è¡åé建äºä¸ä¸ªç¸åçShape::Rectå¼ãå¯ä»¥ä½¿ç¨@模å¼éåè¿æ®µä»£ç ï¼
rect @ Shape::Rect(..) => {
optimized_paint(&rect)
}
2
3
@模å¼å¨å¤çèå´æ¶ä¹å¾æç¨ï¼
match chars.next() {
Some(digit @ '0'..='9') => read_number(digit, chars),
...
},
2
3
4
# 模å¼ç使ç¨åºæ¯
è½ç¶æ¨¡å¼å¨match表达å¼ä¸æä¸ºå¸¸è§ï¼ä½å®ä»¬ä¹å¯ä»¥å¨å
¶ä»å ä¸ªå°æ¹ä½¿ç¨ï¼é常æ¯ç¨æ¥ä»£æ¿æ è¯ç¬¦ãå
¶å«ä¹å§ç»æ¯ç¸åçï¼Rust䏿¯ç®åå°å°ä¸ä¸ªå¼åå¨å¨å个åéä¸ï¼èæ¯ä½¿ç¨æ¨¡å¼å¹é
æ¥åè§£è¿ä¸ªå¼ã
è¿æå³ç模å¼å¯ä»¥ç¨äºâ¦â¦
// ...å°ä¸ä¸ªç»æä½è§£å
为ä¸ä¸ªæ°çå±é¨åé
let Track { album, track_number, title, .. } = song;
// ...è§£å
ä½ä¸ºå½æ°åæ°çå
ç»
fn distance_to((x, y): (f64, f64)) -> f64 { ... }
// ...éåHashMapçé®å¼å¯¹
for (id, document) in &cache_map {
println!("Document #{}: {}", id, document.title);
}
// ...èªå¨è§£å¼ç¨éå
çåæ°
// ï¼è¿å¾æ¹ä¾¿ï¼å ä¸ºææ¶å
¶ä»ä»£ç ä¼ä¼ éç»ä½ ä¸ä¸ªå¼ç¨ï¼èä½ æ´æ³è¦ä¸ä¸ªå¯æ¬ï¼
let sum = numbers.fold(0, |a, &num| a + num);
2
3
4
5
6
7
8
9
10
11
è¿äºç¨æ³æ¯ç§é½èçäºä¸¤ä¸è¡æ ·æ¿ä»£ç ãå ¶ä»ä¸äºè¯è¨ä¹æç¸åçæ¦å¿µï¼å¨JavaScriptä¸ï¼å®è¢«ç§°ä¸ºè§£æï¼destructuringï¼ï¼å¨Pythonä¸ï¼å®è¢«ç§°ä¸ºè§£å ï¼unpackingï¼ã
请注æï¼å¨è¿å个示ä¾ä¸ï¼æä»¬ä½¿ç¨ç模å¼é½æ¯ä¿è¯è½å¹é
çãæ¨¡å¼Point3d { x, y, z }è½å¹é
Point3dç»æä½ç±»åçä»»ä½å¯è½å¼ï¼(x, y)è½å¹é
ä»»ä½(f64, f64)对ï¼ä¾æ¤ç±»æ¨ãå¨Rustä¸ï¼å§ç»è½å¹é
çæ¨¡å¼å¾ç¹æ®ãå®ä»¬è¢«ç§°ä¸ºä¸å¯å驳模å¼ï¼irrefutable patternsï¼ï¼å¹¶ä¸æ¯ä¸è¿°åä¸ªå°æ¹ï¼letä¹åã彿°åæ°ä¸ãforä¹å以åéå
åæ°ä¸ï¼å¯ä¸å
许使ç¨ç模å¼ã
å¯å驳模å¼ï¼refutable patternï¼æ¯å¯è½æ æ³å¹é
çæ¨¡å¼ï¼æ¯å¦Ok(x)ï¼å®æ æ³å¹é
éè¯¯ç»æï¼æè
'0'..='9'ï¼å®æ æ³å¹é
å符'Q'ãå¯å驳模å¼å¯ä»¥ç¨å¨match忝ä¸ï¼å 为matchå°±æ¯ä¸ºå¤çå®ä»¬è设计çï¼å¦æä¸ä¸ªæ¨¡å¼å¹é
å¤±è´¥ï¼æ¥ä¸æ¥ä¼åçä»ä¹æ¯å¾æç¡®çãåé¢çå个示ä¾å±ç¤ºäºå¨Rustç¨åºä¸ï¼æ¨¡å¼å¾æç¨ï¼ä½è¯è¨ä¸å
许å¹é
失败çæ
åµã
å¯å驳模å¼ä¹å¯ä»¥ç¨å¨if letåwhile let表达å¼ä¸ï¼è¿äºè¡¨è¾¾å¼å¯ä»¥ç¨äºâ¦â¦
// ...ç¹å«å¤çä¸ä¸ªæä¸¾åä½
if let RoughTime::InTheFuture(_, _) = user.date_of_birth() {
user.set_time_traveler(true);
}
// ...ä»
å½è¡¨æ¥æ¾æåæ¶è¿è¡ä¸äºä»£ç
if let Some(document) = cache_map.get(&id) {
return send_cached_response(document);
}
// ...åå¤å°è¯æä»¶äºï¼ç´å°æå
while let Err(err) = present_cheesy_anti_robot_task() {
log_robot_attempt(err);
// è®©ç¨æ·åè¯ä¸æ¬¡ï¼å¯è½ä»ç¶æ¯äººç±»å¨æä½ï¼
}
// ...æå¨éåè¿ä»£å¨
while let Some(_) = lines.peek() {
read_paragraph(&mut lines);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
æå ³è¿äºè¡¨è¾¾å¼ç详ç»ä¿¡æ¯ï¼è¯·åé âif letâ å â循ç¯âã
# å¡«å äºåæ
å颿们æ¿è¯ºå±ç¤ºå¦ä½å®ç°BinaryTree::add()æ¹æ³ï¼è¯¥æ¹æ³ç¨äºåå¦ä¸ç±»åçäºåæ 䏿·»å èç¹ï¼
// ä¸ä¸ªæåºçTç±»åå
ç´ éåã
enum BinaryTree<T> {
Empty,
NonEmpty(Box<TreeNode<T>>),
}
// BinaryTreeçä¸é¨åã
struct TreeNode<T> {
element: T,
left: BinaryTree<T>,
right: BinaryTree<T>,
}
2
3
4
5
6
7
8
9
10
11
12
ç°å¨ä½ å·²ç»å¯¹æ¨¡å¼æäºè¶³å¤çäºè§£ï¼å¯ä»¥ç¼åè¿ä¸ªæ¹æ³äºãå ³äºäºåæç´¢æ çè§£éè¶ åºäºæ¬ä¹¦çèå´ï¼ä½å¯¹äºå·²ç»çæè¿ä¸ªä¸»é¢çè¯»è æ¥è¯´ï¼ççå®å¨Rust䏿¯å¦ä½å®ç°çæ¯å¾æä»·å¼çã
impl<T: Ord> BinaryTree<T> {
fn add(&mut self, value: T) {
match *self {
BinaryTree::Empty => {
*self = BinaryTree::NonEmpty(Box::new(TreeNode {
element: value,
left: BinaryTree::Empty,
right: BinaryTree::Empty,
}))
}
BinaryTree::NonEmpty(ref mut node) => {
if value <= node.element {
node.left.add(value);
} else {
node.right.add(value);
}
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
第1è¡åè¯Rustæä»¬æ£å¨ä¸ºæåºç±»åçBinaryTreeå®ä¹ä¸ä¸ªæ¹æ³ãè¿ä¸æä»¬å¨ â使ç¨implå®ä¹æ¹æ³â ä¸å®ä¹æ³åç»æä½æ¹æ³çè¯æ³å®å
¨ç¸åã
å¦æç°æçæ *self为空ï¼é£å°±å¾ç®åã第5 - 9è¡ä»£ç 伿§è¡ï¼å°ç©ºæ å为é空æ ãè¿é对Box::new()çè°ç¨ä¼å¨å ä¸åé
ä¸ä¸ªæ°çTreeNodeã宿åï¼æ ä¸å
å«ä¸ä¸ªå
ç´ ï¼å
¶å·¦åæ åå³åæ å为空ã
妿*selfä¸ä¸ºç©ºï¼æä»¬å¹é
第11è¡ç模å¼ï¼BinaryTree::NonEmpty(ref mut node) => {ã
è¿ä¸ªæ¨¡å¼åç¨äºå¯¹Box<TreeNode<T>>çå¯åå¼ç¨ï¼è¿æ ·æä»¬å°±å¯ä»¥è®¿é®åä¿®æ¹è¯¥æ èç¹ä¸çæ°æ®ãè¿ä¸ªå¼ç¨å为nodeï¼å
¶ä½ç¨åæ¯ä»ç¬¬12è¡å°ç¬¬16è¡ãç±äºè¯¥èç¹ä¸å·²ç»æä¸ä¸ªå
ç´ ï¼ä»£ç å¿
é¡»éå½è°ç¨.add()ï¼å°æ°å
ç´ æ·»å å°å·¦åæ æå³åæ ä¸ã
è¿ä¸ªæ°æ¹æ³å¯ä»¥è¿æ ·ä½¿ç¨ï¼
let mut tree = BinaryTree::Empty;
tree.add("Mercury");
tree.add("Venus");
...
2
3
4
# æ´ä½æ¦è¿°
Rustä¸çæä¸¾å¯¹äºç³»ç»ç¼ç¨æ¥è¯´å¯è½æ¯æ°äºç©ï¼ä½å®å¹¶ä¸æ¯ä¸ä¸ªæ°çæ¦å¿µãå¨åç§å¬èµ·æ¥å¾å¦æ¯çåç§°ä¸ï¼æ¯å¦ä»£æ°æ°æ®ç±»åï¼å®å·²ç»å¨å½æ°å¼ç¼ç¨è¯è¨ä¸ä½¿ç¨äºååå¤å¹´ãç®åè¿ä¸æ¸ æ¥ä¸ºä»ä¹Cè¯è¨ä¼ ç»ä¸çå ¶ä»è¯è¨å¾å°ææä¸¾ç±»åãä¹è®¸åªæ¯å 为对äºç¼ç¨è¯è¨è®¾è®¡è æ¥è¯´ï¼å°åä½ãå¼ç¨ãå¯åæ§åå åå®å ¨æ§ç»åèµ·æ¥æå ·æææ§ã彿°å¼ç¼ç¨è¯è¨æå¼äºå¯åæ§ãç¸æ¯ä¹ä¸ï¼Cè¯è¨ä¸çèåï¼unionsï¼æåä½ãæéåå¯åæ§ï¼ä½å®å ¨æ§æå·®ï¼ä»¥è³äºå³ä½¿å¨Cè¯è¨ä¸ï¼å®ä»¬ä¹æ¯æåçææ®µãRustçåç¨æ£æ¥å¨å°±åä¸ç§éæ³ï¼ä½¿å¾å¨ä¸å¦¥åçæ åµä¸å°è¿åè ç»åæä¸ºå¯è½ã
ç¼ç¨å°±æ¯æ°æ®å¤çãå°æ°æ®å¤çæåéçå½¢å¼ï¼å¯è½ä¼è®©ç¨åºå¨å°åãå¿«éãä¼é ä¸ç¼æ ¢ãåºå¤§ä¸æ··ä¹±ä¹é´äº§ç天壤ä¹å«ã
è¿å°±æ¯æä¸¾æè§£å³çé®é¢ãå®ä»¬æ¯ä¸ç§å°æ°æ®å¤çæåéå½¢å¼çè®¾è®¡å·¥å ·ã对äºä¸ä¸ªå¼å¯è½æ¯æä¸ç§æ åµãå¦ä¸ç§æ åµï¼æè æ ¹æ¬æ²¡æå¼çæ åµï¼æä¸¾å¨å个æ¹é¢é½æ¯ç±»å±æ¬¡ç»ææ´å¥½ï¼é度æ´å¿«ãæ´å®å ¨ãä»£ç æ´å°ãæ´æäºè®°å½ææ¡£ã
å
¶éå¶å ç´ å¨äºçµæ´»æ§ãæä¸¾çæç»ç¨æ·æ æ³æ©å±å®æ¥æ·»å æ°çåä½ãåªæéè¿æ´æ¹æä¸¾å£°ææè½æ·»å åä½ãè䏿¦è¿æ ·åï¼ç°æä»£ç å°±ä¼åºéãæ¯ä¸ªåç¬å¹é
æä¸¾æ¯ä¸ªåä½çmatch表达å¼é½å¿
é¡»éæ°å®¡è§ ââ å®éè¦ä¸ä¸ªæ°ç忝æ¥å¤çæ°çåä½ãå¨æäºæ
åµä¸ï¼ç¨çµæ´»æ§æ¢åç®åæ§æ¯ææºä¹ä¸¾ãæ¯ç«ï¼JSONçç»æé¢è®¡ä¸ä¼æ¹åãå¨æäºæ
åµä¸ï¼å½æä¸¾åçååæ¶éæ°å®¡è§ææä½¿ç¨å®çå°æ¹æ£æ¯æä»¬æ³è¦çãä¾å¦ï¼å½æä¸¾å¨ç¼è¯å¨ä¸ç¨äºè¡¨ç¤ºç¼ç¨è¯è¨çåç§è¿ç®ç¬¦æ¶ï¼æ·»å ä¸ä¸ªæ°è¿ç®ç¬¦åºè¯¥æ¶åä¿®æ¹ææå¤çè¿ç®ç¬¦ç代ç ã
使æ¶éè¦æ´é«ççµæ´»æ§ã对äºè¿äºæ åµï¼Rustæç¹æ§ï¼traitsï¼ï¼è¿æ¯æä»¬ä¸ä¸ç« ç主é¢ã