Rust精简笔记第2部分
继续Rust基础知识点总结,趁假期回顾学习
参考The Rust Programming Language & Rust in Action
八,泛型、Trait、生命周期 泛型:
1 2 3 4 fn largest<T>(list: &[T]) -> T { } //函数 largest 有泛型类型 T。它有个参数 list,其类型是元素为 T 的 slice。largest 函数的返回值类型也是 T //类型参数声明位于函数名称与参数列表中间的尖括号 <>
1 2 3 4 5 6 7 8 9 struct Point <T> { x: T, y: T, } fn main () { let integer = Point { x: 5 , y: 10 }; let float = Point { x: 1.0 , y: 4.0 }; }
1 2 3 4 5 6 7 8 9 enum Option <T> { Some (T), None , } enum Result <T, E> { Ok (T), Err (E), }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 struct Point <T> { x: T, y: T, } impl <T> Point<T> { fn x (&self ) -> &T { &self .x } } fn main () { let p = Point { x: 5 , y: 10 }; println! ("p.x = {}" , p.x()); }
Trait:
通过 trait 以一种抽象的方式定义共享的行为,trait 类似于其他语言中的接口,但也不完全一样.
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 pub trait Summary { fn summarize_author (&self ) -> String ; fn summarize (&self ) -> String { format! ("(Read more from {}...)" , self .summarize_author()) } } pub struct Tweet { pub username: String , pub content: String , pub reply: bool , pub retweet: bool , } impl Summary for Tweet { fn summarize_author (&self ) -> String { format! ("@{}" , self .username) } } fn main () { 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()); }
1 2 3 4 pub fn notify (item: &impl Summary) { println! ("Breaking news! {}" , item.summarize()); }
Trait Bound: impl Trait 适用于短小的例子。trait bound 则适用于更复杂的场景,trait bound 与泛型参数声明在一起,位于尖括号中的冒号后面。
1 2 3 4 5 pub fn notify (item1: &impl Summary, item2: &impl Summary) {}pub fn notify <T: Summary>(item1: &T, item2: &T) {}
1 pub fn notify <T: Summary + Display>(item: &T) {}
1 2 3 4 5 fn some_function <T, U>(t: &T, u: &U) -> i32 where T: Display + Clone , U: Clone + Debug { }
声明周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 fn longest <'a >(x: &'a str , y: &'a str ) -> &'a str { if x.len() > y.len() { x } else { y } } fn main () { let string1 = String ::from("abcd" ); let string2 = "xyz" ; let result = longest(string1.as_str(), string2); println! ("The longest string is {}" , result); }
1 2 3 &i32 &'a i32 &'a mut i32
1 let s: &'static str = "I have a static lifetime." ;
九,集合: vector:
类型是 Vec 在内存中彼此相邻地排列所有的值, vector 只能储存相同类型的值
1 2 3 4 5 let v: Vec <i32 > = Vec ::new();v.push(2 ); v.push(4 ); let x = v.pop();
读取 vector 的元素: 使用 &[index] 返回一个引用, 或者使用 get 方法以索引作为参数来返回一个 Option<&T>。
1 2 3 4 5 6 7 8 9 10 11 fn main () { let v = vec! [1 , 2 , 3 , 4 , 5 ]; let third: &i32 = &v[2 ]; println! ("The third element is {}" , third); match v.get(2 ) { Some (third) => println! ("The third element is {}" , third), None => println! ("There is no third element." ), } }
HashMap 1 2 3 4 5 6 let mut scores = HashMap::new();scores.insert(String ::from("Blue" ), 10 ); scores.entry(String ::from("Yellow" )).or_insert(50 ); scores.entry(String ::from("Blue" )).or_insert(50 ); println! ("{:?}" , scores);
十,函数、闭包、迭代器 函数:
函数的定义方式及在结构体实现里关联函数,关联函数与方法的使用区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 use std::primitive;struct Point { x: i32 , y: i32 , } impl Point { fn new (x: i32 , y: i32 ) -> Point { Point { x: x, y: y } } fn get_x (&self ) -> i32 { self .x } } fn main () { let point = Point::new(5 , 6 ); println! ("get x={}" , point.get_x()); }
闭包:
闭包(closures) 是可以保存在一个变量中或作为参数传递给其他函数的匿名函数。 闭包的定义以一对竖线(|)开始,在竖线中指定闭包的参数
1 2 3 4 fn add_one_v1 (x: u32 ) -> u32 { x + 1 } let add_one_v2 = |x: u32 | -> u32 { x + 1 }; let add_one_v3 = |x| { x + 1 }; let add_one_v4 = |x| x + 1 ;
闭包会捕获其环境:
可以捕获其环境并访问其被定义的作用域的变量。如下边 x 并不是 equal_to_x 的一个参数,equal_to_x 闭包也被允许使用变量 x,因为它与 equal_to_x 定义于相同的作用域
1 2 3 4 5 6 7 fn main () { let x = 4 ; let equal_to_x = |z| z == x; let y = 4 ; assert! (equal_to_x(y)); }
1 2 3 FnOnce 消费从周围作用域捕获的变量,闭包周围的作用域被称为其 环境,environment。为了消费捕获到的变量,闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实,所以它只能被调用一次FnMut 获取可变的借用值所以可以改变其环境Fn 从其环境获取不可变的借用值
由于所有闭包都可以被调用至少一次,所以所有闭包都实现了 FnOnce .大部分需要指定一个 Fn 系列 trait bound 的时候,可以从 Fn 开始,而编译器会根据闭包体中的情况告诉你是否需要 FnMut 或 FnOnce。
带有泛型和 Fn trait 的闭包: 可以创建一个存放闭包和调用闭包结果的结构体, 目的:结构体只会在需要结果时执行闭包,并会缓存结果值,再次调用闭包可以复用该值.
1 2 3 4 5 6 7 struct Cacher <T>where T: Fn (u32 ) -> u32 , { calculation: T, value: Option <u32 >, }
创建Cache的结构体,泛型T类型使用where 声明类型为闭包,结构体包含一个闭包,和一个用于存放闭包返回的值的u32类型,因为有可能第一次没有缓存,所有使用Option的类型。即可能是some(u32) 或者None
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 use std::thread;use std::time::Duration;struct Cacher <T>where T: Fn (u32 ) -> u32 , { calculation: T, value: Option <u32 >, } impl <T> Cacher<T>where T: Fn (u32 ) -> u32 , { fn new (calculation: T) -> Cacher<T> { Cacher { calculation, value: None , } } fn value (&mut self , arg: u32 ) -> u32 { match self .value { Some (v) => v, None => { let v = (self .calculation)(arg); self .value = Some (v); v } } } } fn generate_workout (intensity: u32 , random_number: u32 ) { let mut expensive_result = Cacher::new(|num| { println! ("calculating slowly..." ); thread::sleep(Duration::from_secs(2 )); num }); if intensity < 25 { println! ("Today, do {} pushups!" , expensive_result.value(intensity)); println! ("Next, do {} situps!" , expensive_result.value(intensity)); } else { if random_number == 3 { println! ("Take a break today! Remember to stay hydrated!" ); } else { println! ( "Today, run for {} minutes!" , expensive_result.value(intensity) ); } } } fn main () { let simulated_user_specified_value = 10 ; let simulated_random_number = 7 ; generate_workout(simulated_user_specified_value, simulated_random_number); }
a.这样可以起到了使用结构体缓存了闭包执行的结果,会先从结构体里查找缓存的值,没有再计算。 b.同理也可以改造value的类型为HashMap, 可以通过key来找值,避免返回之前计算的始终同一个值。
iterator:
迭代器(iterator): 负责遍历序列中的每一项和决定序列何时结束的逻辑。
1 2 3 4 let v1 = vec! [1 , 2 , 3 ];let v1_iter = v1.iter();let total: i32 = v1_iter.sum();println! ("value = {}" , { total })
next 是 Iterator 实现者被要求定义的唯一方法
1 2 3 let v1 = vec! [1 , 2 , 3 ];let mut v1_iter = v1.iter();assert_eq! (v1_iter.next(), Some (&1 ));
调用 map 方法创建一个新迭代器,接着调用 collect 方法消费新迭代器并创建一个 vector
1 2 3 4 5 6 7 fn main () { let v1: Vec <i32 > = vec! [1 , 2 , 3 ]; let mut newiter = v1.iter().map(|x| x + 1 ); let newVector: Vec <_> = newiter.collect(); assert_eq! (newVector, vec! [2 , 3 , 4 ]); }
迭代器 iter()、iter_mut()、into_iter()区别:
iter()返回的是值的不可变引用. 即&T
iter_mut() 返回的是值的可变引用. 即&mut T
into_iter() 返回的是T类型的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use core::num;fn main () { let vec = vec! [1 , 2 , 3 , 4 ]; let new_vec: Vec <_> = vec.iter().map(|x| x + 1 ).collect(); println! ("{:?}" , vec); println! ("{:?}" , new_vec); let mut vec = vec! [1 , 2 , 3 , 4 ]; vec.iter_mut().for_each(|x| *x += 1 ); println! ("{:?}" , vec); let vec = vec! [1 , 2 , 3 , 4 ]; let new_vec: Vec <_> = vec.into_iter().filter(|x| *x == 2 ).collect(); println! ("{:?}" , new_vec); }
实现Iterator trait 来创建自定义迭代器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 struct Counter { count: u32, } impl Counter { fn new() -> Counter { Counter { count: 0 } } } //Counter 类型实现 Iterator trait,通过定义 next 方法来指定使用迭代器时的行为 impl Iterator for Counter { type Item = u32; //将迭代器的关联类型 Item 设置为 u32,意味着迭代器会返回 u32 值集合 fn next(&mut self) -> Option<Self::Item> { if self.count < 5 { self.count += 1; Some(self.count) } else { None } } }
1 2 3 4 5 pub trait Iterator { type Item ; fn next (&mut self ) -> Option <Self::Item>; }
更多信息请添加公众号