Rust学习笔记

Rust编程语言入门教程课程笔记

参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)

Lecture 10: Generic Types, Traits, and Lifetimes

lib.rs

1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::fmt::Display;

//Traits: Defining Shared Behavior
pub trait Summary {
fn summarize_author(&self) -> String;

// fn summarize(&self) -> String;
fn summarize(&self) -> String {
//String::from("(Read more from...)")
format!("(Read more from {}...)", self.summarize_author())
}

}

pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}

impl Summary for NewsArticle {//implementing a trait on a type
// fn summarize(&self) -> String {//implementing a trait method
// format!("{}, by {} ({})", self.headline, self.author, self.location)
// }
fn summarize_author(&self) -> String {//implementing a trait method
format!("{}", self.author)
}

}

pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}

impl Summary for Tweet {//implementing a trait on a type
fn summarize(&self) -> String {//implementing a trait method
format!("{}: {}", self.username, self.content)
}
fn summarize_author(&self) -> String {//implementing a trait method
format!("{}", self.username)
}

}

pub fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}

pub fn notify_trait_bound<T: Summary>(item: &T) {//trait bound syntax
println!("Breaking news! {}", item.summarize());
}

pub fn notify_trait_bounds<T: Summary>(item1: &T, item2: &T) {//trait bound syntax
println!("Breaking news! {}", item1.summarize());
println!("Breaking news! {}", item2.summarize());
}

pub fn notify_multiple_trait_bounds<T: Summary + Display>(item1: &T, item2: &T) {//trait bound syntax
println!("Breaking news! {}", item1.summarize());
println!("Breaking news! {}", item2.summarize());
}

pub fn notify_where_clause<T, U>(item1: &T, item2: &U)
where T: Summary + Display,
U: Summary + Display
{
println!("Breaking news! {}", item1.summarize());
println!("Breaking news! {}", item2.summarize());
}

//Returning Types that Implement Traits
fn _returns_summarizable() -> impl Summary {
//returning a type that implements the Summary trait
//cannot return different types
Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
}
}

struct _Pair<T> {
x: T,
y: T,
}

impl <T> _Pair<T> {
fn _new(x: T, y: T) -> Self {
Self {
x,
y,
}
}

}

impl <T: Display + PartialOrd> _Pair<T> {//trait bound syntax
fn _cmp_display(&self) {
if self.x >= self.y {
println!("The largest member is x = {}", self.x);
} else {
println!("The largest member is y = {}", self.y);
}
}

}

//blanket implementations
// impl<T: Display> ToString for T {
// // --snip--
// }

main.rs

1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
use generic_types_traits_and_lifetimes::Summary;
use generic_types_traits_and_lifetimes::Tweet;
use std::fmt::Display;

//Generic Data Types
fn largest_generic<T:std::cmp::PartialOrd + Clone>(list: &[T]) -> &T {
let mut largest = &list[0];

for item in list {
if item > largest { //error: the trait `std::cmp::PartialOrd` is not implemented for `T`
largest = item;
}
}

largest
}

struct Point<T> {
x: T,
y: T,
}

impl Point<i32> {
fn selfx(&self) -> &i32 {
&self.x
}

}

impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}

impl Point<&str>{
fn concatenate(&self) -> String {
format!("{}{}", self.x, self.y)
}
}

#[derive(Debug)]
struct Point2<T, U> {
x: T,
y: U,
}

impl<T, U> Point2<T, U> {
fn mixup<V, W>(self, other: Point2<V, W>) -> Point2<T, W> {
Point2 {
x: self.x,
y: other.y,
}
}
}

//Lifetime Annotations in Struct Definitions
struct _ImportantExcerpt<'a> {
_part: &'a str,
}

fn main() {
//remove duplication by extracting the match expression into a function
let number_list = vec![34, 50, 25, 100, 65];

// let mut largest = &number_list[0];

// for number in &number_list {
// if number > largest {
// largest = number;
// }
// }

//largest function with generic type
let result1 = largest(&number_list);

println!("The largest number is {}", result1);

//duplication
let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];

// let mut largest = &number_list[0];

// for number in &number_list {
// if number > largest {
// largest = number;
// }
// }

//largest function with generic type
let result2 = largest(&number_list);

println!("The largest number is {}", result2);


let str_list = vec!["Hello", "Rust", "World"];
let result3 = largest_generic(&str_list);
println!("The largest string is {}", result3);

//Generic Data Types in Struct Definitions
let integer = Point { x: 5, y: 10 };
println!("x,y = {},{}", integer.x, integer.y);
let float = Point { x: 1.0, y: 4.0 };
println!("x,y = {},{}", float.x, float.y);

//Generic Data Types in Enum Definitions
let integer = Option::Some(5);
let float = Option::Some(5.0);
let none: Option<i32> = None;
println!("integer = {:?}, float = {:?}, none = {:?}", integer, float, none);
println!("integer = {:?}, float = {:?}, none = {:?}", integer, float, none);

//Generic Data Types in Method Definitions
let p1 = Point { x: 5, y: 10 };
let p2 = Point { x: "Hello", y: " Rust" };
let p3 = Point { x: 5.0, y: 10.0 };
println!("p1:{}",p1.selfx());
println!("p2:{}",p2.concatenate());
println!("p3:{}",p3.distance_from_origin());

//Generic Data Types in Struct Definitions
let p4 = Point2 { x: 5, y: 10.4 };
let p5: Point2<&str, i32> = Point2 {x:"Hello", y:2};
println!("p4:{:?}",p4.mixup(p5));

//Traits: Defining Shared Behavior
let tweet = Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
};

println!("1 new tweet: {}", tweet.summarize());

//Lifetimes: Ensuring One Borrow Lasts as Long as the Other
//avoiding dangling references

// let r;
// //let b = r;//error: use of possibly uninitialized `r`
// {
// let x = 5;
// r = &x;
// }
// //borrow checker
// //println!("r:{}",r);//error: `x` does not live long enough

let x = 5;
let r = &x;
println!("r:{}",r);

let string1 = String::from("abcd");
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);

//Lifetime Annotations in Struct Definitions
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().expect("Could not find a '.'");
let _i = _ImportantExcerpt { _part: first_sentence };

//Lifetime Elision

}

fn largest(list: &[i32]) -> &i32 {//we need to return a reference to the value
let mut largest = &list[0];

for number in list {
if number > largest {
largest = number;
}
}

largest
}

//Lifetime Annotation Syntax
//'a is a generic lifetime parameter
//&'a str: a string slice that lives for the lifetime 'a
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {//we need to return a reference to the value
//'a is the part of the scope of x that overlaps with the scope of y
if x.len() > y.len() {
x
} else {
y
}
}

fn _longest<'a>(x: &'a str, _y: &str) -> &'a str {//we need to return a reference to the value
//'a is the part of the scope of x that overlaps with the scope of y
x
}

// fn error_longest<'a>(x: &str, _y: &str) -> &'a str {//we need to return a reference to the value
// let result = String::from("really long string");
// result.as_str()
// }

fn _corroct_longest<'a>(_x: &'a str, _y: &str) -> String {//we need to return a reference to the value
let result = String::from("really long string");
result
}

//Lifetime Elision
//The compiler uses three rules to figure out what lifetimes references have when there aren’t explicit annotations.
//The first rule applies to input lifetimes, and the second and third rules apply to output lifetimes.
//If the compiler gets to the end of the three rules and there are still references for which it can’t figure out lifetimes, the compiler will stop with an error.

//1. Each parameter that is a reference gets its own lifetime parameter.
//2. If there is exactly one input lifetime parameter, that lifetime is assigned to all output lifetime parameters: fn foo<'a>(x: &'a i32) -> &'a i32.
//3. If there are multiple input lifetime parameters, but one of them is &self or &mut self because this is a method, the lifetime of self is assigned to all output lifetime parameters.

fn _first_word(s: &str) -> &str {
let bytes = s.as_bytes();

for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}

&s[..]
}

fn _longest_with_an_announcement<'a, T>(
x: &'a str,
y: &'a str,
ann: T,
) -> &'a str
where T: Display
{
println!("Announcement! {}", ann);
if x.len() > y.len() {
x
} else {
y
}
}