rust 闭包(一)

简介: rust 闭包

闭包

闭包是一种匿名函数,它可以赋值给变量也可以作为参数传递给其它函数,不同于函数的是,它允许捕获调用者作用域中的值,例如:

fn main() {
   let x = 1;
   let sum = |y| x + y;
    assert_eq!(3, sum(2));
}

上面的代码展示了非常简单的闭包 sum,它拥有一个入参 y,同时捕获了作用域中的 x 的值,因此调用 sum(2) 意味着将 2(参数 y)跟 1(x)进行相加,最终返回它们的和:3。

可以看到 sum 非常符合闭包的定义:可以赋值给变量,允许捕获调用者作用域中的值。

使用闭包来简化代码
传统函数实现

想象一下,我们要进行健身,用代码怎么实现,这里是我的想法:

use std::thread;
use std::time::Duration;
// 开始健身,好累,我得发出声音:muuuu...
fn muuuuu(intensity: u32) -> u32 {
    println!("muuuu.....");
    thread::sleep(Duration::from_secs(2));
    intensity
}
fn workout(intensity: u32, random_number: u32) {
    if intensity < 25 {
        println!(
            "今天活力满满,先做 {} 个俯卧撑!",
            muuuuu(intensity)
        );
        println!(
            "旁边有妹子在看,俯卧撑太low,再来 {} 组卧推!",
            muuuuu(intensity)
        );
    } else if random_number == 3 {
        println!("昨天练过度了,今天还是休息下吧!");
    } else {
        println!(
            "昨天练过度了,今天干干有氧,跑步 {} 分钟!",
            muuuuu(intensity)
        );
    }
}
fn main() {
    // 强度
    let intensity = 10;
    // 随机值用来决定某个选择
    let random_number = 7;
    // 开始健身
    workout(intensity, random_number);
}

可以看到,在健身时我们根据想要的强度来调整具体的动作,然后调用 muuuuu 函数来开始健身。这个程序本身很简单,没啥好说的,但是假如未来不用 muuuuu 函数了,是不是得把所有 muuuuu 都替换成,比如说 woooo ?如果 muuuuu 出现了几十次,那意味着我们要修改几十处地方。

闭包实现
use std::thread;
use std::time::Duration;
fn workout(intensity: u32, random_number: u32) {
    let action = || {
        println!("muuuu.....");
        thread::sleep(Duration::from_secs(2));
        intensity
    };
    if intensity < 25 {
        println!(
            "今天活力满满,先做 {} 个俯卧撑!",
            action()
        );
        println!(
            "旁边有妹子在看,俯卧撑太low,再来 {} 组卧推!",
            action()
        );
    } else if random_number == 3 {
        println!("昨天练过度了,今天还是休息下吧!");
    } else {
        println!(
            "昨天练过度了,今天干干有氧,跑步 {} 分钟!",
            action()
        );
    }
}
fn main() {
    // 动作次数
    let intensity = 10;
    // 随机值用来决定某个选择
    let random_number = 7;
FnOnce,该类型的闭包会拿走被捕获变量的所有权。Once 顾名思义,说明该闭包只能运行一次:
    // 开始健身
    workout(intensity, random_number);
}

在上面代码中,无论你要修改什么,只要修改闭包 action 的实现即可,其它地方只负责调用,完美解决了我们的问题!

Rust 闭包在形式上借鉴了 Smalltalk 和 Ruby 语言,与函数最大的不同就是它的参数是通过 |parm1| 的形式进行声明,如果是多个参数就 |param1, param2,…|, 下面给出闭包的形式定义:

|param1, param2,...| {
    语句1;
    语句2;
    返回表达式
}
闭包的类型推导

与函数相反,闭包并不会作为 API 对外提供,因此它可以享受编译器的类型推导能力,无需标注参数和返回值的类型。

下面展示了同一个功能的函数和闭包实现形式:

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  ;

虽然类型推导很好用,但是它不是泛型,当编译器推导出一种类型后,它就会一直使用该类型:

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

首先,在 s 中,编译器为 x 推导出类型 String,但是紧接着 n 试图用 5 这个整型去调用闭包,跟编译器之前推导的 String 类型不符,因此报错:

error[E0308]: mismatched types
 --> src/main.rs:5:29
  |
5 |     let n = example_closure(5);
  |                             ^
  |                             |
  |                             expected struct `String`, found integer // 期待String类型,却发现一个整数
  |                             help: try using a conversion method: `5.to_string()`
结构体中的闭包

假设我们要实现一个简易缓存,功能是获取一个值,然后将其缓存起来,那么可以这样设计:

  • 一个闭包用于获取值
  • 一个变量,用于存储该值
    可以使用结构体来代表缓存对象,最终设计如下:
struct Cacher<T>
where
    T: Fn(u32) -> u32,
{
    query: T,
    value: Option<u32>,
}


rust 闭包(二)https://developer.aliyun.com/article/1391991

相关文章
|
存储 Rust 程序员
rust中的函数:定义、调用与闭包
本文将深入探讨Rust编程语言中函数的定义、调用方式,以及闭包(closures)的概念和应用。我们将从函数的基本语法出发,逐步深入到函数的参数传递、返回值,再进一步介绍闭包及其捕获环境的能力,帮助读者全面理解并熟练运用Rust中的函数与闭包。
|
缓存 Rust 编译器
|
设计模式 缓存 Rust
Rust学习笔记之闭包和迭代器
1. 函数式编程 推荐阅读指数 ⭐️⭐️⭐️⭐️ 2. 闭包:可以捕获环境的匿名函数 推荐阅读指数 ⭐️⭐️⭐️⭐️⭐️ 3. 使用迭代器处理元素序列 推荐阅读指数 ⭐️⭐️⭐️⭐️⭐️
403 0
Rust学习笔记之闭包和迭代器
|
Rust 自然语言处理
【RUST学习日记】第20课 闭包
【RUST学习日记】第20课 闭包
|
Rust 安全 Java
探索Rust语言的并发编程模型
探索Rust语言的并发编程模型
553 2
|
Rust 安全 区块链
探索Rust语言:系统编程的新选择
【10月更文挑战第27天】Rust语言以其安全性、性能和并发性在系统编程领域受到广泛关注。本文介绍了Rust的核心特性,如内存安全、高性能和强大的并发模型,以及开发技巧和实用工具,展示了Rust如何改变系统编程的面貌,并展望了其在WebAssembly、区块链和嵌入式系统等领域的未来应用。
|
Rust 安全 编译器
编程语言新宠:Rust语言的特性、优势与实战入门
【10月更文挑战第26天】Rust语言诞生于2006年,由Mozilla公司的Graydon Hoare发起。作为一门系统编程语言,Rust专注于安全和高性能。通过所有权系统和生命周期管理,Rust在编译期就能消除内存泄漏等问题,适用于操作系统、嵌入式系统等高可靠性场景。
2104 2
|
Rust 安全 Java
编程语言新宠:Rust语言的特性、优势与实战入门
【10月更文挑战第27天】Rust语言以其独特的特性和优势在编程领域迅速崛起。本文介绍Rust的核心特性,如所有权系统和强大的并发处理能力,以及其性能和安全性优势。通过实战示例,如“Hello, World!”和线程编程,帮助读者快速入门Rust。
1935 1
|
Rust 安全 调度
从零构建梦想操作系统:用Rust语言亲手打造专属内核,你也可以成为系统开发者!
【8月更文挑战第31天】开发操作系统内核虽具挑战,却也充满乐趣。本文将指导你从零开始,使用Rust语言构建一个简单的操作系统内核。首先安装Rust环境和交叉编译工具链,然后创建新项目`my_kernel`。通过修改`Cargo.toml`和编写启动函数,结合串口输出和`multiboot2`库,最终使用QEMU运行内核。此教程旨在帮助你理解Rust在系统开发中的应用,激发深入探索的兴趣。
1613 2
|
Rust 安全 算法
揭秘Rust语言如何重塑区块链安全:打造坚不可摧的分布式账本新篇章!
【8月更文挑战第31天】自比特币诞生以来,区块链技术凭借其去中心化和不可篡改的特点备受关注。为了应对安全性挑战,Rust 语言凭借其内存安全特性逐渐成为区块链开发的优选。本文探讨了 Rust 如何助力区块链实现更安全的分布式账本。通过示例展示了 Rust 在避免内存泄漏、空指针引用及数据竞争等方面的优势,预示着 Rust 在高性能、高安全性需求的区块链应用中拥有广阔前景。
639 2