研读Rust圣经解析——Rust learn-11(测试,迭代器,闭包)

这篇具有很好参考价值的文章主要介绍了研读Rust圣经解析——Rust learn-11(测试,迭代器,闭包)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

测试

测试我不打算很详细的写,大家知道如何使用其实就差不多了

编写测试模块

一般来说我们在lib中编写测试

cargo new test_01 --lib

这样我们构建了一个test的lib
在这个工程里面你看到应该是有个lib.rs没有main.rs的
研读Rust圣经解析——Rust learn-11(测试,迭代器,闭包)

声明test模块

这里并不是声明一个mod,而是一个测试区域,在区域中可以写很多的测试方法

我们通过#[cfg(test)]宏来进行标注

#[cfg(test)]
mod tests {
  
}

编写测试方法

测试方法和普通方法没什么区别,主要在于标注#[test]

 #[test]
    fn test01() {
        assert_eq!(6, 4);
    }

执行测试

我们使用cargo test就可以启动进行测试了,测试会将所有标注#[test]的方法都测试一遍

测试结果检查

我们通常使用assert检查测试结果

  1. assert:断言结果为true,否则panic
  2. assert_eq:断言两边相等,否则panic
  3. assert_ne:断言两边不等,否则panic

闭包

一个可以储存在变量里的类似函数的结构

Rust 的 闭包(closures)是可以保存在一个变量中或作为参数传递给其他函数的匿名函数。可以在一个地方创建闭包,然后在不同的上下文中执行闭包运算。不同于函数,闭包允许捕获被定义时所在作用域中的值。我们将展示闭包的这些功能如何复用代码和自定义行为。

定义一个闭包

如下,我们使用||{}定义了一个闭包,很像是函数的写法:

fn main() {
    let a = || {
        10
    };
    println!("{}",a());
}

这个闭包会返回10,但是实际a的类型是fn:fn->i32,对于但语句来说将{}省略也是OK的

完整写法

|参数|->返回值{
	//...
}

闭包可以捕获环境

如下的闭包中使用到了b变量,但是b没有传入闭包,这就和函数有了差别,使得我们在做一些简单的,不用复用的操作的时候可以直接使用闭包而不是定义一个函数

fn main() {
    let b = 16;
    let a = |x:i32| {
        b * x
    };
    println!("{}",a(10));
}

闭包类比函数

这里给出圣经中的例子:

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  ;

闭包类型推断

我们看这个程序,看上去没任何问题,但是实际上会报错,原因就是闭包类型推断,前面我们知道闭包会自动推断类型,所以当第一次执行的时候,闭包认为返回值是String,第二次再次调用相同的闭包导致了返回值类型不一致,所以报错:

fn main() {
    let example_closure = |x| x;

    let s = example_closure(String::from("hello"));
    let n = example_closure(5);
}

闭包获取所有权

闭包体不严格需要所有权,如果希望强制闭包获取它用到的环境中值的所有权,可以在参数列表前使用 move 关键字
在将闭包传递到一个新的线程时这个技巧很有用,它可以移动数据所有权给新线程

move ||->返回值类型{
	
}

将被捕获的值移出闭包和 Fn trait

闭包捕获和处理环境中的值的方式影响闭包实现的 trait。Trait 是函数和结构体指定它们能用的闭包的类型的方式。取决于闭包体如何处理值,闭包自动、渐进地实现一个、两个或三个 Fn trait。

  1. FnOnce 适用于能被调用一次的闭包,所有闭包都至少实现了这个 trait,因为所有闭包都能被调用。一个会将捕获的值移出闭包体的闭包只实现 FnOnce trait,这是因为它只能被调用一次。
  2. FnMut 适用于不会将捕获的值移出闭包体的闭包,但它可能会修改被捕获的值。这类闭包可以被调用多次。
  3. Fn 适用于既不将被捕获的值移出闭包体也不修改被捕获的值的闭包,当然也包括不从环境中捕获值的闭包。这类闭包可以被调用多次而不改变它们的环境,这在会多次并发调用闭包的场景中十分重要。

迭代器

迭代器模式允许你对一个序列的项进行某些处理。迭代器(iterator)负责遍历序列中的每一项和决定序列何时结束的逻辑。当使用迭代器时,我们无需重新实现这些逻辑。
迭代器是惰性的:调用方法使用迭代器前无效

创建一个迭代器

调用复合类型的iter方法即可创建,但此时无效

fn main() {
    let arr = vec![123];
    let item_iter = arr.iter();
}

应用迭代器遍历

以下是使用for对迭代器进行遍历

fn main() {
    let mut arr = Vec::new();
    arr.push(1);
    arr.push(2);
    let item_iter = arr.iter();
    for item in item_iter {
        println!("{}",item)
    }
}

使用foreach配合闭包遍历

fn main() {
    let mut arr = Vec::new();
    arr.push(1);
    arr.push(2);
    let item_iter = arr.iter();
    item_iter.for_each(|x|println!("{}",x))
}

通过模拟hasNext进行遍历

fn main() {
    let mut arr = Vec::new();
    arr.push(1);
    arr.push(2);
    let mut item_iter = arr.iter();
    let mut i = item_iter.len();
    while i != 0 {
        println!("{}", item_iter.next().unwrap());
        i = i - 1;
    }
}

next方法

迭代器的next方法返回的是一个Option<T>这样一个对象

sum方法

这个方法一样会消费迭代器,因为获取迭代器的所有权并反复调用 next 来遍历迭代器

let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let total: i32 = v1_iter.sum();

迭代器适配器

Iterator trait 中定义了另一类方法,被称为 迭代器适配器(iterator adaptors),他们允许我们将当前迭代器变为不同类型的迭代器。可以链式调用多个迭代器适配器。不过因为所有的迭代器都是惰性的,必须调用一个消费适配器方法以便获取迭代器适配器调用的结果。

fn main() {
    let mut arr = Vec::new();
    arr.push(1);
    arr.push(2);
    let new_arr:Vec<_> = arr.iter().map(|x| x + 4).collect();
    println!("{:?}", new_arr);
}

这里我们使用map对迭代器中的每个元素进行操作,最后使用collect收集为新的集合类型

迭代器的性能

实际上迭代器更快,因为迭代器,作为一个高级的抽象,被编译成了与手写的底层代码大体一致性能代码。迭代器是 Rust 的 零成本抽象(zero-cost abstractions)之一,它意味着抽象并不会引入运行时开销
详细大家可以看这里:
https://kaisery.github.io/trpl-zh-cn/ch13-04-performance.html文章来源地址https://www.toymoban.com/news/detail-421614.html

到了这里,关于研读Rust圣经解析——Rust learn-11(测试,迭代器,闭包)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Rust】Rust学习 第十三章Rust 中的函数式语言功能:迭代器与闭包

    Rust 的设计灵感来源于很多现存的语言和技术。其中一个显著的影响就是  函数式编程 ( functional programming )。函数式编程风格通常包含将函数作为参数值或其他函数的返回值、将函数赋值给变量以供之后执行等等。 更具体的,我们将要涉及: 闭包 ( Closures ),一个可以储

    2024年02月12日
    浏览(51)
  • 【跟小嘉学 Rust 编程】十三、函数式语言特性:迭代器和闭包

    【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学 Rust 编程】六、枚举

    2024年02月11日
    浏览(57)
  • Rust编程语言入门之函数式语言特性:-迭代器和闭包

    闭包(closures) 迭代器(iterators) 优化改善 12 章的实例项目 讨论闭包和迭代器的运行时性能 闭包:可以捕获其所在环境的匿名函数。 闭包: 是匿名函数 保存为变量、作为参数 可在一个地方创建闭包,然后在另一个上下文中调用闭包来完成运算 可从其定义的作用域捕获值

    2023年04月08日
    浏览(44)
  • 【Rust 基础篇】Rust 闭包

    在 Rust 中,闭包(closures)是一种函数对象,它可以捕获其环境中的变量,并在需要时调用。闭包提供了一种方便的方式来封装行为,并在需要时进行调用。本篇博客将详细介绍 Rust 中的闭包,包括闭包的定义、语法、捕获变量的方式以及一些常见的使用场景。 闭包在 Rust 中

    2024年02月16日
    浏览(38)
  • 【python高级用法】迭代器、生成器、装饰器、闭包

    可迭代对象:可以使用for循环来遍历的,可以使用isinstance()来测试。 迭代器:同时实现了__iter__()方法和__next__()方法,可以使用isinstance()方法来测试是否是迭代器对象 使用类实现迭代器 两个类实现一个迭代器 一个类实现迭代器 可迭代对象与迭代器的总结 一个具备了__iter_

    2024年02月03日
    浏览(37)
  • rust学习-闭包

    模拟健康推荐算法,为前端提供高强度/低强度的训练app simulated_expensive_calculation 是个算法模块维护的内容,且未来变化较大,所以代码中期待对其只使用一次。 闭包不要求像 fn 函数那样在参数和返回值上注明类型 函数需要类型标注是因为是暴露给用户的显式接口的一部分

    2024年02月16日
    浏览(41)
  • rust 闭包函数

    函数有自己的类型,可以像使用基础类型一样使用函数,包括将函数保存在变量中、保存在 vec 中、声明在结构体成员字段中。闭包函数也是函数,也有自己的类型定义。不过,函数实际上是指针类型,在 rust 所有权中属于借用的关系。 我们声明一个 Vec 对象集,并使用闭包

    2024年02月15日
    浏览(41)
  • Rust- 闭包

    A closure in Rust is an anonymous function you can save in a variable or pass as an argument to another function. You can create the closure using a lightweight syntax and access variables from the scope in which it’s defined. Here’s an example of a closure that increases a number by one: In this example, plus_one is a closure that takes one argument x a

    2024年02月14日
    浏览(31)
  • 【Rust 基础篇】Rust 迭代器

    在 Rust 中,迭代器(iterators)是一种提供序列化访问元素的抽象方式。迭代器允许我们对集合中的元素进行遍历和处理,而无需显式地处理索引或使用循环。通过使用迭代器,我们可以编写简洁、可读性强且安全的代码。本篇博客将详细介绍 Rust 中的迭代器,包括迭代器的定

    2024年02月16日
    浏览(40)
  • 【Rust 基础篇】Rust 自定义迭代器

    在 Rust 中,自定义迭代器可以帮助我们根据特定需求实现符合自己逻辑的迭代过程。自定义迭代器是通过实现 Iterator trait 来完成的。本篇博客将详细介绍如何在 Rust 中自定义迭代器,包括自定义迭代器的定义、必要的方法和一些常见的使用场景。 自定义迭代器需要实现 Ite

    2024年02月15日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包