X

曜彤.手记

随记,关于互联网技术、产品与创业

吉 ICP 备10004938-2号

《The Rust Programming Language》读书笔记(第 17-21 章)


书接上回,第 17-21 章的笔记。

Chapter 17 - Object Oriented Programming Features of Rust

  1. (Page:408)Rust 中的 OOP:
  1. (Page:412)Trait Object
pub trait Draw {
    fn draw(&self);
}

// version 1: generic struct + trait bounds.
// pub struct Screen<T: Draw> {
//     pub components: Vec<T>,
// }
// impl<T> Screen<T> 
//     where T: Draw, {
//         pub fn run(&self) {
//             for component in self.components.iter() {
//                 component.draw(); 
//             }
//         }
//     }

// version 2: struct + trait object.
pub struct Screen {
    pub components: Vec<Box<dyn Draw>>,  // trait object.
}
impl Screen {
    pub fn run(&self) {
        for component in self.components.iter() { 
            component.draw();
        } 
    }
}
  1. (Page:419)实现“面向对象”设计模式:
pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}
impl Post {
    pub fn new() -> Post {
        Post {
            state: Some(Box::new(Draft {})),
            content: String::new(),
        }
    }
    pub fn content(&self) -> &str {
        // get a reference to the value inside the "Option".
        self.state.as_ref().unwrap().content(self)
    }
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text);
    }
    pub fn request_review(&mut self) {
        // take the ownership and setup a new one.
        if let Some(s) = self.state.take() {
            self.state = Some(s.request_review());
        }
    }
    pub fn approve(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.approve()) 
        }
    }
}

trait State {
    // the method is only valid when called on a "Box" holding the type.
    fn request_review(self: Box<Self>) -> Box<dyn State>;
    fn approve(self: Box<Self>) -> Box<dyn State>;
    fn content<'a>(&self, post: &'a Post) -> &'a str { "" }
}

struct Draft {}
impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview {})
    }
    fn approve(self: Box<Self>) -> Box<dyn State> { 
        self
    }
}

struct PendingReview {}
impl State for PendingReview {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }
    fn approve(self: Box<Self>) -> Box<dyn State> { 
        Box::new(Published {})
    }
}

struct Published {}
impl State for Published {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }
    fn approve(self: Box<Self>) -> Box<dyn State> { 
        self
    } 
    fn content<'a>(&self, post: &'a Post) -> &'a str { 
        &post.content
    }
}
pub struct Post {
    content: String,
}
pub struct DraftPost {
    content: String,
}
impl Post {
    pub fn new() -> DraftPost {
        DraftPost {
            content: String::new(),
        } 
    }
    pub fn content(&self) -> &str { 
        &self.content
    } 
}
impl DraftPost {
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text); 
    }
    pub fn request_review(self) -> PendingReviewPost {
        PendingReviewPost {
            content: self.content, 
        }
    }
}
pub struct PendingReviewPost {
    content: String,
}
impl PendingReviewPost {
    pub fn approve(self) -> Post {
        Post {
            content: self.content,
        } 
    }
}
fn main() {
    let mut post = Post::new();
    post.add_text("I ate a salad for lunch today");
    let post = post.request_review();
    let post = post.approve();
    assert_eq!("I ate a salad for lunch today", post.content()); 
}

Chapter 18 - Patterns and Matching

  1. (Page:433)一个“模式”包含对下面这些元素的组合:
  1. (Page:436)Rust 中的几种模式匹配场景:

while…let条件循环

fn main() {
    let mut stack = Vec::new();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    while let Some(top) = stack.pop() {
        println!("{}", top);
    }
}
fn main() {
    let v = vec!['a', 'b', 'c'];
    // the pattern is "(index, value)".
    for (index, value) in v.iter().enumerate() { 
      println!("{} is at index {}", value, index);
    }
}
fn print_coordinates(&(x, y): &(i32, i32)) { 
    println!("Current location: ({}, {})", x, y);
}
fn main() {
    let point = (3, 5); 
    print_coordinates(&point);
}
  1. (Page:439)Refutability
if let Some(x) = a_value {}
let x = 5;
  1. (Page:442)模式匹配语法
let x = 1;
match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    _ => println!("anything"),
}
let x = Some(5); 
let y = 10;
match x {
    Some(50) => println!("Got 50"),
    // this newly introduced variable "y" will shadow the outer one.
    Some(y) => println!("Matched, y = {:?}", y), 
    _ => println!("Default case, x = {:?}", x),
}
println!("at the end: x = {:?}, y = {:?}", x, y);
let x = 1;
match x {
    // match 1 or 2.
    1 | 2 => println!("one or two"), 
    3 => println!("three"),
    _ => println!("anything"),
}
let x = 5;
match x {
    // match value within [1, 5].
    1..=5 => println!("one through five"), 
    _ => println!("something else"),
} 
let y = 'c';
match y {
    'a'..='j' => println!("early ASCII letter"), 
    'k'..='z' => println!("late ASCII letter"), 
    _ => println!("something else"),
}
struct Point {
    x: i32,
    y: i32,
}
fn main() {
    let p = Point { x: 0, y: 7 };
    // shorthand.
    let Point { x, y } = p;
    assert_eq!(0, x); 
    assert_eq!(7, y);

    // destructure with literal values as part of the struct pattern.
    match p {
        Point { x, y: 0 } => println!("On the x axis at {}", x),
        Point { x: 0, y } => println!("On the y axis at {}", y),
        Point { x, y } => println!("On neither axis: ({}, {})", x, y),
    }
}
enum Color {
    Rgb(i32, i32, i32),
    Hsv(i32, i32, i32),
}
struct Upgrade {
    id: i32, time: i32
}
enum Message {
    Quit,
    Move { x: i32, y: i32, },
    Write(String),
    ChangeColor(Color),
    Upgrade(Upgrade)
}
fn main() {
    let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
    match msg {
        Message::Quit => {}
        Message::Move { x, y } => {}
        Message::Write(str) => {}
        Message::ChangeColor(Color::Hsv(h, s, v)) => {}
        Message::ChangeColor(Color::Rgb(r, g, b)) => {}
        Message::Upgrade(Upgrade { id, time }) => {}
    }
}
  1. (Page:449)忽略模式中的部分值
fn foo(_: i32, y: i32) {
    println!("This code only uses the y parameter: {}", y);
}
fn main() {
    foo(3, 4);
}
let mut setting_value = Some(5); 
let new_setting_value = Some(10);
match (setting_value, new_setting_value) { 
    (Some(_), Some(_)) => {
        println!("Can't overwrite an existing customized value");
    }
    _ => {
        setting_value = new_setting_value;
    } 
}
println!("setting is {:?}", setting_value);
struct Point {
    x: i32,
    y: i32,
    z: i32, 
}
let origin = Point { x: 0, y: 0, z: 0 };
match origin {
    Point { x, .., z } => println!("x is {}, z is {}", x, z),
}
  1. (Page:453)Match Grard:在 match-arm 中可以额外使用的 if 关键字;在进行匹配时,该 if 所表达的条件也需要被匹配。
let num = Some(4);
match num {
    Some(x) if x < 5 => println!("less than five: {}", x), 
    Some(x) => println!("{}", x),
    None => (),
}
  1. (Page:455)@ 绑定:
enum Message {
    Hello { id: i32 },
}
let msg = Message::Hello { id: 5 };
match msg {
    Message::Hello {
        id: id @ 3..=7,  // create a variable "id" that holds a value of the tested value.
    } => println!("Found an id in range: {}", id), 
    Message::Hello { id: 10..=12 } => {
        println!("Found an id in another range")
    }
    Message::Hello { id } => println!("Found some other id: {}", id), 
}

Chapter 19 - Advanced Features

  1. (Page:457)不安全的 Rust:

- 解引用一个原始指针

fn main() { 
    let mut num = 5;
    // let r1: *const i32 = &num;
    // let r2: *mut i32 = &mut num;
    let r1 = &num as *const i32;  // immutable raw pointer.
    let r2 = &mut num as *mut i32;  // mutable raw pointer.
    let r3 = &mut num;
    unsafe {
        println!("{}", *r1);
        println!("{}", *r2);
        println!("{}", r3);
    }
}

- 调用不安全的函数或方法

fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { 
    let len = slice.len();
    let ptr = slice.as_mut_ptr();
    assert!(mid <= len);
    unsafe { 
        (
            std::slice::from_raw_parts_mut(ptr, mid),
            // move raw pointer forward.
            std::slice::from_raw_parts_mut(ptr.add(mid), len - mid), 
        )
    } 
}
// a Rust function can be called from C, used by compiling to a shared library and linked from C.
#[no_mangle]
pub extern "C" fn call_from_c() {
    println!("Just called a Rust function from C!");
}
extern "C" {
    fn abs(input: i32) -> i32;
}
fn main() { 
    unsafe {
        println!("Absolute value of -3 according to C: {}", abs(-3));
    }
}

- 访问或修改可变的静态变量

static mut COUNTER: u32 = 0;
fn add_to_count(inc: u32) {
    unsafe {
        COUNTER += inc;
    }
}
fn main() { 
    add_to_count(3);
    unsafe {
        println!("COUNTER: {}", COUNTER);
    }
}

- 实现不安全的 trait

unsafe trait Foo {}
unsafe impl Foo for i32 {}

- 访问 Union 中的字段:同 C/C++ 中的 union 类似。

union MyUnion {
    f1: u32,
    f2: f32,
}
fn main() { 
    let u = MyUnion { f1: 1 };
    let f = unsafe {
        println!("{}", u.f1);
    };
}
  1. (Page:467)高级 Traits

- 使用 Associated Types 为 trait 指定“占位”类型

// trait "Iterator" from std.
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>; 
}

- 默认泛型类型参数与运算符重载

use std::ops::Add;

// the "Rhs" of the Add operation is the the type we’re implementing Add on.
// trait Add<Rhs=Self> {  
//     type Output;
//     fn add(self, rhs: Rhs) -> Self::Output; 
// }

#[derive(Debug, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}
// impl Add<Point> for Point { ...
impl Add for Point {  // the default "Rhs" would be the "Point".
    type Output = Point;  // determines the type returned from the add method.
    fn add(self, other: Point) -> Point {
        Point {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}
fn main() { 
    assert_eq!(
        Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
        Point { x: 3, y: 3 }
    )
}

- 用于消除歧义的语法:调用具有相同名称的方法

trait Pilot {
    fn fly(&self);
}
trait Wizard {
    fn fly(&self);
}
struct Human;
impl Pilot for Human {
    fn fly(&self) {
        println!("This is your captain speaking.");
    }
}
impl Wizard for Human {
    fn fly(&self) {
        println!("Up.");
    }
}
impl Human {
    fn fly(&self) {
        Wizard::fly(self);
        println!("*waving arms furiously*");
    }
}
fn main() { 
    let person = Human; 
    Pilot::fly(&person);
    Wizard::fly(&person);
    Human::fly(&person);
    person.fly();
}
trait Animal {
    fn baby_name() -> String;
}
struct Dog;
impl Dog {
    fn baby_name() -> String {
        String::from("Spot")
    }
}
impl Animal for Dog {
    fn baby_name() -> String {
        String::from("puppy")
    }
}
fn main() { 
    // use "fully qualified syntax" to point out which one we want to call.
    println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
}

- 一个 trait 的实现依赖于另一个 trait 提供的功能

use std::fmt;
// the "OutlinePrint" trait requires "fmt::Display" trait.
trait OutlinePrint: fmt::Display { 
    fn outline_print(&self) {
        let output = self.to_string();  // call the method defined on the "fmt::Display" trait.
        let len = output.len(); 
        println!("{}", "*".repeat(len + 4)); 
        println!("*{}*", " ".repeat(len + 2)); 
        println!("* {} *", output); 
        println!("*{}*", " ".repeat(len + 2)); 
        println!("{}", "*".repeat(len + 4));
    } 
}
struct Point {
    x: i32,
    y: i32, 
}
impl OutlinePrint for Point {}
impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y) 
    }
}
fn main() { 
    Point { x: 1, y: 1 }.outline_print();
}

- 在外部类型上“实现”外部 trait

use std::fmt;
use std::ops::Deref;
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]", self.0.join(", ")) 
    }
}
impl Deref for Wrapper {
    type Target = Vec<String>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
fn main() {
    let w = Wrapper(vec![String::from("hello"), String::from("world")]); 
    println!("w = {}", w);
    println!("{}", w.join(" | "));  // call the methods on the warpped value (by implementing "Defer").
}
  1. (Page:479)高级类型

- 使用“类型别名”创建同义类型

// an example from the std::io module.
// type Result<T> = std::result::Result<T, std::io::Error>;
type Kilometers = i32;  // a type alias for i32.
let x: i32 = 5;
let y: Kilometers = 5;
println!("x + y = {}", x + y);

- Never 类型!

- 动态大小类型(DSTs)与 Sized trait

fn generic<T>(t: T) {}
fn generic<T: Sized>(t: T) {}  // by default, the size of T should be known at compile time.
// "T may or may not be Sized" (this syntax only works for the Sized trait).
fn generic<T: ?Sized>(t: &T) {}  
  1. (Page:486)高级函数与闭包

- 函数指针

fn add_one(x: i32) -> i32 {
    x + 1
}
// accept a function pointer.
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
    f(arg) + f(arg)
}
fn main() {
    let answer = do_twice(add_one, 5);
    println!("The answer is: {}", answer);
}
enum Status {
    Value(u32),
    Stop, 
}
let list_of_statuses: Vec<Status> = (0u32..20).map(Status::Value).collect();

- 返回闭包(函数)

// we can return a function pointer directly.
fn returns_function() -> fn(i32) -> i32 { 
    |x| x + 1
}
// closures are represented by traits, so we can’t return closures directly.
fn returns_closure() -> Box<dyn Fn(i32) -> i32> { 
    Box::new(|x| x + 1)
}
  1. (Page:489)
  1. (Page:490)声明式宏
#[macro_export]
macro_rules! vec {
    // similar to the "match" expression.
    // captures values that match the pattern within the parentheses.
    // "$x:expr" matches any Rust expression and gives the expression the name $x.
    ( $( $x:expr ), * ) => {
        // $x pattern matches three times with 1, 2 and 3.
        {
            let mut temp_vec = Vec::new();
            // generated for each part that matches $() in the pattern zero or more times.
            $(
                temp_vec.push($x);
            )*
            // temp_vec.push(1); 
            // temp_vec.push(2); 
            // temp_vec.push(3);
            temp_vec
        }
    };
}
fn main() {
    let v: Vec<u32> = vec![1,2, 3];
    println!("{:#?}", v);
}
  1. (Page:492)用于从属性生成代码的“过程式宏”
// the definition of the trait.
pub trait HelloMacro {
    fn hello_macro();
}
// the definition of the macro for the trait.
extern crate proc_macro;
// the compiler’s API that allows us to read and manipulate Rust code.
use proc_macro::TokenStream; 
// turns "syn" data structures back into Rust code.
use quote::quote;
// parses Rust code from a string into a data structure.
use syn;

#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // construct a representation of Rust code as a syntax tree 
    // that we can manipulate
    let ast = syn::parse(input).unwrap();
    // Build the trait implementation
    impl_hello_macro(&ast) 
}
fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    // the name of the struct implementing this trait.
    let name = &ast.ident;
    // define the Rust code that we want to return.
    let gen = quote! {
        impl HelloMacro for #name { 
            fn hello_macro() {
                // converting "#name" to a string literal at compile time.
                println!("Hello, Macro! My name is {}!", stringify!(#name));
            }
        } 
    };
    gen.into()
}
// the usage of the macro.
use hello_macro::HelloMacro;
use hello_macro_derive::HelloMacro;

#[derive(HelloMacro)]
struct Pancakes;
fn main() { 
    Pancakes::hello_macro();
}
  1. (Page:498)类属性宏
// the usage of the attribute-like macro.
#[route(GET, "/")]
fn index() {}
// the definition of the macro.
// the first parameter is for the contents of the attribute: the [GET, "/"] part.
// the second is the body of the item the attribute is attached to, namely [fn index() {}].
#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {}
  1. (Page:499)类函数宏
// the usage of the function-like macro.
let sql = sql!(SELECT * FROM posts WHERE id=1);
// the definition of the macro.
// receive the tokens that are inside the parentheses and return the code we wanted to generate.
#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {}

Chapter 20 - Final Project: Building a Multithreaded Web Server

(略)

Chapter 21 - Appendix

  1. (Page:544)Raw Identifier
fn r#match() {
    println!("the function name is called {}", "match");
}
fn main() {
    r#match();
}
  1. (Page:551)可继承的 traits
  1. (Page:555)相关工具


这是文章底线,下面是评论
  暂无评论,欢迎勾搭 :)