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[..]
}
5.Using Structs to Structure Related Data
//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() {}