Rust编程语言入门教程课程笔记
参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)
lib.rs
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 ToString for T {
// // --snip--
// }
main.rs
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
}
}