Rust编程语言-13-函数式编程(闭包和迭代器)

Rust语言的设计吸收了许多其它语言的优秀设计,比如函数式编程和闭包

闭包closure

能捕获环境参数的匿名函数

fn  add_one_v1   (x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 };
let add_one_v3 = |x|             { x + 1 };
let add_one_v4 = |x|               x + 1  ;

Rust中定义了Fn, FnMut, FnOnce几种Trait

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
            }
        }
    }
}
  • FnOnce:Once代表了move,变量只能被移动一次,不能被多次夺取所有权
  • FnMut:可变借用,可以多次
  • Fn:不可变借用
fn main() {
    let x = vec![1, 2, 3];

    let equal_to_x = move |z| z == x;

    println!("can't use x here: {:?}", x);

    let y = vec![1, 2, 3];

    assert!(equal_to_x(y));
}
  • move: 强制move,一般用做把变量引入线程中

Iterator

Rust中Iterator是懒加载的,就是在consume之前实际上什么都没有执行,如下代码,因为没有consume,实际上什么都没做(与Java的lambda表达式类似)

fn main() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
}

  • into_iter() vs iter()
  • iter_mut() vs iter()

#![allow(unused)]
fn main() {
pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;

    // methods with default implementations elided
}
}
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> {
        if self.count < 5 {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[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);
    }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 变量 声明变量关键字:let 变量值分为两种类型: 可变的(mut) 不可变 变量类型: 布尔型 - bool 表...
    JennerHua阅读 940评论 0 4
  • Rust 的 闭包(closures)是可以保存进变量或作为参数传递给其他函数的匿名函数。可以在一个地方创建闭包,...
    梁帆阅读 1,436评论 0 2
  • Rust 编程语言入门教程 第一章: Rust简介 为什么要用Rust Rust是一种令人兴奋的新编程语言, 它可...
    快乐2020阅读 1,101评论 0 0
  • RUST 学习日记 第21课 ——迭代器(Iterator) 0x00 回顾与开篇 关于函数的学习暂时告一段落了...
    L我是小学生阅读 584评论 0 1
  • 引子 Rust对函数式编程有着非常良好的支持,从闭包这一特性就能看出来,它不仅实现了经典的功能和语义,还派生出Fn...
    Loru_vest阅读 2,190评论 0 1