函数-method 闭包 迭代器

方法跟函数类似:都是使用 fn 声明,有参数和返回值。但是与函数不同的是,方法定义在结构体的上下文中(枚举、特征对象也可以定义方法),而且方法的第一个参数一定是 self 或其变体 &self&mut selfself 代表了当前调用的结构体实例。

self 会拿走当前结构体实例(调用对象)的所有权,而 &self 却只会借用一个不可变引用,&mut self 会借用一个可变引用。

fn another_function() {
    let x = 5;

    let y = {
        let x = 1;
        x+3
    };

    println!("The value of y is: {}",y);

命名规则:蛇形命名法2,add_two类似。

函数的返回值就是函数体最后一条表达式的返回值,当然我们也可以使用 return 提前返回

单元类型 (),是一个零长度的元组。它没啥作用,但是可以用来表达一个函数没有返回值:

  • 函数没有返回值,那么返回一个 ()

  • 通过 ; 结尾的表达式返回一个 ()

关联函数 & 方法

关联函数的调用不是通过点操作符,而是使用 `::~,方法才是通过点操作符调用。

关联函数与方法最大的区别就是它第一个参数不是 self ,原因是它们不需要使用当前的实例,因此关联函数往往可以用于构造函数:初始化一个实例对象。

闭包

move会把所有权进行转移。

增加 move 关键字,我们强制闭包获取其使用的值的所有权

move 关键字覆盖了 Rust 默认保守的借用,但它不允许我们违反所有权规则

闭包定义会为每个参数和返回值推断一个具体类型。

可以创建一个存放闭包和调用闭包结果的结构体,该结构体只会在需要结果时执行闭包,并会缓存结果值,这样余下的代码就不必再负责保存结果并可以复用该值。你可能见过这种模式被称 memoizationlazy evaluation (惰性求值)

为了让结构体存放闭包,我们需要指定闭包的类型,因为结构体定义需要知道其每一个字段的类型。每一个闭包实例有其自己独有的匿名类型:也就是说,即便两个闭包有着相同的签名,他们的类型仍然可以被认为是不同。为了定义使用闭包的结构体、枚举或函数参数,需要使用泛型和 trait bound。

Fn 系列 trait 由标准库提供。所有的闭包都实现了 trait FnFnMutFnOnce 中的一个。

trait bound 就是 Fn(u32) -> u32,存放了闭包和一个 Option 结果值的 Cacher 结构体。

注意:函数也都实现了这三个 Fn trait。如果不需要捕获环境中的值,则可以使用实现了 Fn trait 的函数而不是闭包。

为了展示闭包作为函数参数时捕获其环境的作用,迭代器。

迭代器

在 Rust 中,迭代器是 惰性的lazy),这意味着在调用方法使用迭代器之前它都不会有效果。一旦创建迭代器之后,可以选择用多种方式利用它。

迭代器处理了所有这些逻辑,这减少了重复代码并消除了潜在的混乱。

迭代器的实现方式提供了对多种不同的序列使用相同逻辑的灵活性,而不仅仅是像 vector 这样可索引的数据结构。

迭代器都实现了一个叫做 Iterator 的定义于标准库的 trait。

新语法:type ItemSelf::Item,他们定义了 trait 的 关联类型associated type)。

实现 Iterator trait 要求同时定义一个 Item 类型,这个 Item 类型被用作 next 方法的返回值类型。换句话说,Item 类型将是迭代器返回元素的类型。

nextIterator 实现者被要求定义的唯一方法。next 一次返回迭代器中的一个项,封装在 Some 中,当迭代器结束时,它返回 None

需要注意到从 next 调用中得到的值是 vector 的不可变引用。iter 方法生成一个不可变引用的迭代器。如果我们需要一个获取 v1 所有权并返回拥有所有权的迭代器,则可以调用 into_iter 而不是 iter。类似的,如果我们希望迭代可变引用,则可以调用 iter_mut 而不是 iter

sum 之后不再允许使用 v1_iter 因为调用 sum 时它会获取迭代器的所有权。

自定义迭代器

Last updated