hello_closures 0.1.0

hello closures and iterator
Documentation
//零成本抽象到底是什么意思?"他们使得代码看起来更高级,但并不为此引入运行时性能损失"
//闭包和迭代器是 Rust 受函数式编程语言观念所启发的功能。他们对 Rust 以底层的性能来明确的表达高级概念的能力有很大贡献。闭包和迭代器的实现达到了不影响运行时性能的程度。这正是 Rust 竭力提供零成本抽象的目标的一部分。

use std::thread;
use std::time::Duration;

fn simulated_expensive_calculation(num: u32) -> u32 {
    println!("calculate is slowly ...");
    thread::sleep(Duration::from_secs(2));

    num
}

pub fn generate_workout(intensity: u32, random_number: u32) {
    //let calculation_closure = |num| {
    let mut calculation_closure = Cacher::new(|num| {
        println!("calculate is slowly ...");
        thread::sleep(Duration::from_secs(2));

        num
    });
    if intensity > 25 {
        //println!("Today, do {} pushups!", simulated_expensive_calculation(intensity));
        //println!("Next, do {} situps!", simulated_expensive_calculation(intensity));
        println!("Today, do {} pushups!", calculation_closure.value(intensity));
        println!("Next, do {} situps!", calculation_closure.value(intensity));
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!("Today, run for {} minutes!", calculation_closure.value(intensity));
        }
    }
}

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
            },
        }
    }
}

#[test]
fn iterator_demonstration() {
    let v1 = vec![1,2,3];
    let mut v1_item = v1.iter();
    assert_eq!(v1_item.next(), Some(&1));
    assert_eq!(v1_item.next(), Some(&2));
    assert_eq!(v1_item.next(), Some(&3));
    assert_eq!(v1_item.next(), None);
}

#[test]
fn iterator_sum() {
    let v1 = vec![1,2,3];
    let v1_iter = v1.iter();
    let total: i32 = v1_iter.sum();
    assert_eq!(total, 6);
}

#[derive(PartialEq, Debug)]//assert_eq中进行比较和打印内容进行的比较
struct Shoe {
    size: u32,
    style: String,
}

fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|shoe| shoe.size == shoe_size)//过滤方法
        .collect()//执行迭代过滤,生成新的迭代器,集合
}

#[test]
fn filters_by_size() {
    let shoes = vec![
        Shoe {size: 10, style: String::from("sneaker")},
        Shoe {size: 12, 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!(sum, 18);
}

/// 这是一个字符串搜索方法
///
/// # Example
/// ```
/// let query = "name";
/// let contents = "
/// My Name is Jeff,
/// The City is named \"山城\"
/// ";
/// let result = hello_closures::search(query, contents);
/// assert_eq!(
///     result,
///     [
///         "The City is named \"山城\"",
///     ]
/// )
/// ```
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents.lines()
        .filter(|s| s.contains(query))
        .collect()
}