wqpw_blog

= =

View on GitHub
7 October 2019

Rust简单整理(c4-c6)

by wqpw

基于官方教程《The Rust Programming Language》

4. Understanding Ownership

/*
Each value in Rust has a variable that's called its owner.
There can only be one owner at a time.
When the owner gose out of scope, the value will be dropped.
*/
fn main() {
    let mut s = String::from("hello"); //on the heap
    s.push_str(", world!");
    //let s1 = s; move to s1, s moved
    let s1 = s.clone(); //deep copy
    println!("{} {}", s, s1);
    let x = 5;
    let y = x; //on the stack just copy
    println!("{} {}", x, y);
    let s = String::from("hello");  // s comes into scope
    takes_ownership(s);             // s's value moves into the function...
                                    // ... and so is no longer valid here
    let x = 5;                      // x comes into scope
    makes_copy(x);                  // x would move into the function,
                                    // but i32 is Copy, so it’s okay to still
                                    // use x afterward
} // Here, x goes out of scope, then s. But because s's value was moved, nothing
  // special happens.
fn takes_ownership(some_string: String) { // some_string comes into scope
    println!("{}", some_string);
} // Here, some_string goes out of scope and `drop` is called. The backing
  // memory is freed.
fn makes_copy(some_integer: i32) { // some_integer comes into scope
    println!("{}", some_integer);
} // Here, some_integer goes out of scope. Nothing special happens.
fn main2() {
    let s1 = gives_ownership();         // gives_ownership moves its return
                                        // value into s1

    let s2 = String::from("hello");     // s2 comes into scope

    let s3 = takes_and_gives_back(s2);  // s2 is moved into
                                        // takes_and_gives_back, which also
                                        // moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was
  // moved, so nothing happens. s1 goes out of scope and is dropped.

fn gives_ownership() -> String {             // gives_ownership will move its
                                             // return value into the function
                                             // that calls it
    let some_string = String::from("hello"); // some_string comes into scope
    some_string                              // some_string is returned and
                                             // moves out to the calling
                                             // function
}
// takes_and_gives_back will take a String and return one
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into scope
    a_string  // a_string is returned and moves out to the calling function
}

//rf.rs
fn main() {
    let mut s1 = String::from("Hello");
    let len = calculate_length(&s1);
    println!("{} {}", s1, len);
    let s2 = test(&mut s1);
    println!("{}", s2);
    let r1 = &s1;
    let r2 = &s1;
    println!("{} {}", r1, r2);
    // reference’s scope starts from where it is introduced
    // and continues through the last time that reference is used.
    //At any given time, you can have either one mutable reference
    // or any number of immutable references.
    //References must always be valid.
    let r3 = &mut s1;
    println!("{}", r3);
}
fn calculate_length(s: &String) -> usize {
    s.len()
}
fn test(s: &mut String) -> &String {
    s.push_str("test");
    s
}

//slice.rs
fn main() {
    let s = String::from("hello rust");
    let s1 = first_word(&s);
    println!("{}", &s[0..s1]); //[,) 0..s1==..s1, 3..==3..s.len() ..=s
    println!(" {} ", new_first_word(&s));
}
fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        // the second element is a reference to the element
        if item == b' ' {
            return i;
        }
    }
    s.len()
}
fn new_first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}
//struct.rs
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}
fn build_user(email: String, username: String) -> User {
    User {
        //email: email,
        //username: username,
        //field init shorthand syntax, parameter have the same name
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
}
fn main() {
    let mut user1 = User {
        username: String::from("msyb"),
        email: String::from("a@a.com"),
        active: true,
        sign_in_count: 1,
    };
    user1.email = String::from("b@b.com");
    println!("{}", user1.username);
    let user2 = build_user(String::from("w@w.com"), String::from("test"));
    println!("{}", user2.username);
    //struct update syntax
    let user2 = User {
        email: String::from("c@c.com"),
        username: String::from("ha"),
        ..user1
    };
    println!("{}", user2.sign_in_count);
    struct Color(i32, i32, i32); //tuple struct. give a name. own type
    let black = Color(0, 0, 0);
    println!("{}", black.0);
}

//rectangles.rs
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
impl Rectangle {
    fn area(&self) -> u32 { //method
        self.width * self.height
    }
    //change. &mut self. take ownership. self
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}
impl Rectangle {
    //associated functions
    fn square(size: u32) -> Rectangle {
        Rectangle {width: size, height: size}
    }
}
fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };

    println!(
        "The area of the rectangle is {} square pixels.",
        area(&rect1)
    );
    println!("rect1 is {:?}", rect1);
    println!("{}", rect1.area());
    let sq = Rectangle::square(3);
    println!("{}", sq.area());
}
//not take ownership
fn area(rectangle: &Rectangle) -> u32 {
    rectangle.width * rectangle.height
}

6.Enums and Pattern Matching

//rust_enum.rs
// Create an `enum` to classify a web event. Note how both
// names and type information together specify the variant:
// `PageLoad != PageUnload` and `KeyPress(char) != Paste(String)`.
// Each is different and independent.
enum WebEvent {
    // An `enum` may either be `unit-like`,
    PageLoad,
    PageUnload,
    // like tuple structs,
    KeyPress(char),
    Paste(String),
    // or c-like structures.
    Click { x: i64, y: i64 },
}
// A function which takes a `WebEvent` enum as an argument and
// returns nothing.
fn inspect(event: WebEvent) {
    match event {
        WebEvent::PageLoad => println!("page loaded"),
        WebEvent::PageUnload => println!("page unloaded"),
        // Destructure `c` from inside the `enum`.
        WebEvent::KeyPress(c) => println!("pressed '{}'.", c),
        WebEvent::Paste(s) => println!("pasted \"{}\".", s),
        // Destructure `Click` into `x` and `y`.
        WebEvent::Click { x, y } => {
            println!("clicked at x={}, y={}.", x, y);
        },
    }
}
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i+1),
    }
}
fn test() {
    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
    let x = 233;
    match x {
        1 => println!("One."),
        _ => (), //match any value => unit value
    }
}
fn if_let_test() {
    let t = Some(0u8);
    match t {
        Some(3) => println!("three"),
        _ => (),
    }
    let t = Some(3); //just need match one pattern / ignoring the rest
    if let Some(3) = t { //a pattern and an expression separated by an equal sign
        println!("three");
    } //else {}
}
fn main() {
    let pressed = WebEvent::KeyPress('x');
    // `to_owned()` creates an owned `String` from a string slice.
    let pasted  = WebEvent::Paste("my text".to_owned());
    let click   = WebEvent::Click { x: 20, y: 80 };
    let load    = WebEvent::PageLoad;
    let unload  = WebEvent::PageUnload;
    inspect(pressed);
    inspect(pasted);
    inspect(click);
    inspect(load);
    inspect(unload);
    test();
    if_let_test();
}

//restaurant
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
        fn seat_at_table() {}
    }
    mod serving {
        fn take_order() {}
        fn serve_order() {}
        fn take_payment() {}
    }
}
pub fn eat_at_restaurant() { //crate::eat_at_res
    // Absolute path
    crate::front_of_house::hosting::add_to_waitlist();
    // Relative path
    front_of_house::hosting::add_to_waitlist();
    //The front_of_house module is defined 
    //within the same module as eat_at_restaurant
}
fn serve_order() {}
mod back_of_house {
    fn fix_incorrect_order() {
        cook_order();
        super::serve_order(); // super -> ../
    }
    fn cook_order() {}
}
fn main() {}
/*
crate
 └── front_of_house
     ├── hosting
     │   ├── add_to_waitlist
     │   └── seat_at_table
     └── serving
         ├── take_order
         ├── serve_order
         └── take_payment
*/
mod back_of_house {
    pub struct Breakfast {
        pub toast: String,
        seasonal_fruit: String, //private
    }
    impl Breakfast {
        pub fn summer(toast: &str) -> Breakfast {
            Breakfast {
                toast: String::from(toast),
                seasonal_fruit: String::from("peaches"),
            }
        }
    }
pub fn eat_at_restaurant() {
    // Order a breakfast in the summer with Rye toast
    let mut meal = back_of_house::Breakfast::summer("Rye");
    // Change our mind about what bread we'd like
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);
    // The next line won't compile if we uncomment it; we're not allowed
    // to see or modify the seasonal fruit that comes with the meal
    // meal.seasonal_fruit = String::from("blueberries");
}
mod back_of_house {
    pub enum Appetizer {
        Soup,
        Salad, //all pub
    }
}
pub fn eat_at_restaurant() {
    let order1 = back_of_house::Appetizer::Soup;
    let order2 = back_of_house::Appetizer::Salad;
}
/*---------------*/
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}
use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}
/*-------*/
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}
use crate::front_of_house::hosting::add_to_waitlist;
pub fn eat_at_restaurant() {
    add_to_waitlist();
    add_to_waitlist();
    add_to_waitlist();
}
/*-------*/
use std::fmt; //std::fmt::Result
use std::io; // std::io::Result not allow
use std::fmt::Result;
use std::io::Result as IoResult; //rename
fn function1() -> fmt::Result {
    // --snip--
    Ok(())
}
fn function2() -> io::Result<()> {
    // --snip--
    Ok(())
}
/*-----------------------*/
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}
pub use crate::front_of_house::hosting;
//bringing an item into scope 
//but also making that item available for others 
//to bring into their scope.
pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}
use std::cmp::Ordering;
use std::io;
use std::{cmp::Ordering, io};
use std::io;
use std::io::Write;
use std::io::{self, Write};
use std::collections::*; //global
//brings all public items defined in std::collections into the current scope
//src/lib.rs
mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}
//src/front_of_house.rs
pub mod hosting;
//src/front_of_house/hosting.rs
pub fn add_to_waitlist() {}
tags: blog