wqpw_blog

= =

View on GitHub
7 October 2019

Rust简单整理(c13-c14)

by wqpw

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

13. Functional Language Features: Iterators and Closures

use std::thread;
use std::time::Duration;
use std::collections::HashMap;
fn main() {
    let simulated_user_specified_value = 10;
    let simulated_random_number = 7;
    let mut val: HashMap<u32, u32> = HashMap::new();
    generate_workout(
        simulated_user_specified_value,
        simulated_random_number,
        &mut val
    );
}
struct Cacher<'a, T>
    where T: Fn(u32) -> u32
{
    calculaltion: T,
    value: Option<u32>,
    val: &'a mut HashMap<u32, u32>,
}
impl<'a, T> Cacher<'a, T>
    where T: Fn(u32) -> u32
{
    fn new(calculaltion: T, val: &'a mut HashMap<u32, u32>) -> Cacher<T> {
        Cacher {
            calculaltion,
            value: None,
            val,
        }
    }
    fn value(&mut self, arg: u32) -> Option<&u32> {
        match self.val.get(&arg) {
            Some(v) => {
                println!("{}", &v);
                self.val.get(&v)
            },
            None => {
                let v = (self.calculaltion)(arg);
                self.val.insert(v, v);
                self.value = Some(v);
                self.value.as_ref()
            },
        }
    }
}
fn generate_workout(intensity: u32, random_number: u32, val: &mut HashMap<u32, u32>) {
    let mut expensive_result = Cacher::new(|num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    }, val);
    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)
            );
        }
    }
}
#[test]
fn call_with_different_values() {
    let mut val: HashMap<u32, u32> = HashMap::new();
    let mut c = Cacher::new(|a| a, &mut val);

    let v1 = c.value(1);
    let v2 = c.value(2);
    let v3: u32 = 2;
    assert_eq!(v2, Some(&v3));
}
/*
fn  add_one_v1   (x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 }; explicit
let add_one_v3 = |x|             { x + 1 }; 
let add_one_v4 = |x|               x + 1  ; one expression
Closure definitions will have one concrete type 
inferred for each of their parameters and for their return value.
closures can capture their environment 
and access variables from the scope in which they’re defined.

FnOnce take ownership only once
FnMut mutably borrows values, can change env
Fn immutably
let equal_to_x = move |z| z == x; force FnOnce
*/

//iter.rs
#![allow(unused_variables)]
fn main() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter(); //return &value
    //into_iter take ownership, return value
    //iter_mut return &mut
    for val in v1_iter {
        println!("Got: {}", val);
    }
    let v1: Vec<i32> = vec![1, 2, 3];
    let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); //return collection
    assert_eq!(v2, vec![2, 3, 4]);
    let v2 = v2.iter().map(|x| x + 1); //return new iter()
//map() just run at iter() was consumed
    for val in v2 {
        println!("v2: {}", val);
    }
}
#[test]
fn iterator_demonstration() {
    let v1 = vec![1, 2, 3];
    let mut v1_iter = v1.iter();
    assert_eq!(v1_iter.next(), Some(&1));
    assert_eq!(v1_iter.next(), Some(&2));
    assert_eq!(v1_iter.next(), Some(&3));
    assert_eq!(v1_iter.next(), None);
}
#[test]
fn iterator_sum() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
    let total: i32 = v1_iter.sum(); //sum take ownership
    assert_eq!(total, 6);
}
#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}
fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|s| s.size == shoe_size)
        .collect()
}
#[test]
fn filters_by_size() {
    let shoes = vec![
        Shoe { size: 10, style: String::from("sneaker") },
        Shoe { size: 13, style: String::from("sandal") },
        Shoe { size: 10, style: String::from("boot") },
    ];
    let in_my_size = shoes_in_my_size(shoes, 10);
    assert_eq!(
        in_my_size,
        vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 10, style: String::from("boot") },
        ]
    );
}
struct Counter {
    count: u32,
}
impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}
impl Iterator for Counter {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}
#[test]
fn calling_next_directly() {
    let mut counter = Counter::new();

    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}
#[test]
fn using_other_iterator_trait_methods() {
    let sum: u32 = Counter::new().zip(Counter::new().skip(1))
                                 .map(|(a, b)| a * b)
                                 .filter(|x| x % 3 == 0)
                                 .sum();
    assert_eq!(18, sum);
}

14. More About Cargo and Crates.io

自动生成文档

//! # Art
//!
//! A library for modeling artistic concepts.
pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;
//now we can
//use art::PrimaryColor;
//use art::mix;
pub mod kinds {
    /// The primary colors according to the RYB color model.
    pub enum PrimaryColor {
        Red,
        Yellow,
        Blue,
    }
    /// The secondary colors according to the RYB color model.
    pub enum SecondaryColor {
        Orange,
        Green,
        Purple,
    }
}
pub mod utils {
    use crate::kinds::*;

    /// Combines two primary colors in equal amounts to create
    /// a secondary color.
    pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        // --snip--
        SecondaryColor::Orange
    }
}

/*
[profile.dev]
opt-level = 1
cargo doc
cargo doc --open
cargo install
workspace ......
*/
tags: blog