Rust 闭包

在 Rust 中,闭包是匿名的函数。它们也被称为匿名函数或 lambda。

在 Rust 中定义闭包

以下是在 Rust 中创建闭包的方法,

// define a closure to print a text
let print_text = || println!("Defining Closure");

在上面的示例中,我们创建了一个打印文本“定义闭包”的闭包。这里,

  • print_text - 用于存储闭包的变量
  • || - 闭包的开始
  • println!("定义闭包") - 闭包的主体

调用闭包

一旦定义了闭包,我们就需要像调用函数一样调用它。要调用闭包,我们使用闭包被赋值到的变量名。例如,

// define a closure to print a text
let print_text = || println!("Defining Closure");

// call the closure
print_text();

在这里,print_text() 调用了闭包。


示例:Rust 中的闭包

fn main() {
    // closure that prints a text
    let print_text = || println!("Hello, World!");
    
    print_text(); 
}

输出

Hello, World!

在上面的示例中,我们定义了一个闭包并将其存储在 print_text 变量中。然后我们使用 print_text() 调用该闭包。


Rust 闭包带参数

在 Rust 中,我们也可以向闭包传递参数。例如,

// define closure to add 1 to an integer
let add_one = |x: i32| x + 1;

这里,

  • let add_one - 是用于存储闭包的变量名
  • |x: i32| - 是传递给闭包的参数及其类型
  • x + 1; - 是闭包的主体,它返回 x + 1

如果我们创建一个带参数的闭包,我们也需要在调用闭包时传递该值。

// call the closure with value 2
add_one(2);

示例:带参数的 Rust 闭包

fn main() {
// define a closure and store it in a variable let add_one = |x: i32| x + 1; // call closure and store the result in a variable let result = add_one(2);
println!("Result = {}", result); }

输出

Result = 3

在上面的示例中,我们定义了一个闭包并将其绑定到 add_one 变量。然后我们使用 add_one(2) 调用该闭包,并将返回值绑定到 result 变量。

程序的工作原理如下,

Working of closure with parameter in Rust
Rust 中带参数的闭包工作原理

Rust 中的多行闭包

我们也可以在闭包中包含多个语句。在这种情况下,我们使用花括号 {} 将这些语句括起来。

让我们看一个例子。

fn main() {
    // define a multi-line closure
    let squared_sum = |x: i32, y: i32| {
    
        // find the sum of two parameters
        let mut sum: i32 = x + y;
        
        // find the squared value of the sum
        let mut result: i32 = sum * sum;
        
        return result;
    };
    
    // call the closure
    let result = squared_sum(5, 3);
    
    println!("Result = {}", result);
}

输出

Result = 64

在上面的示例中,我们创建了一个接受两个参数:xy 的闭包。在闭包内部,我们将 xy 相加,并将结果赋给 sum 变量。

最后,我们计算了和的平方并返回了 result

这里,花括号 {} 中的代码表示闭包的主体。


Rust 中的闭包环境捕获

闭包有一个独特的功能,允许它捕获环境。这意味着闭包可以使用其作用域中的值。例如,

fn main() {
    let num = 100;
    
    // A closure that captures the num variable
    let print_num = || println!("Number = {}", num);
    
    print_num(); 
}

输出

Number = 100

在这里,绑定到 print_num 的闭包使用了变量 num,而 num 并不是在闭包内部定义的。这称为闭包环境捕获。


Rust 中的闭包环境捕获模式

闭包的环境捕获可以根据变量和闭包的定义分为 3 种不同的模式。

  1. 闭包内不修改变量
  2. 闭包内修改变量
  3. 闭包内移动变量

让我们看一下每种环境捕获模式。

1. 闭包内不修改变量

fn main() {
    let word = String::from("Hello");
    
// immutable closure let print_str = || { println!("word = {}", word); };
// immutable borrow is possible outside the closure println!("length of word = {}", word.len()); print_str(); }

输出

word = Hello
length of word = 5

在这里,变量 word 在闭包 print_str 中没有被修改。由于变量默认是不可变的,我们可以在闭包内对 word 进行任意数量的不可变引用。请注意,闭包变量 print_str 也是不可变的。

这种捕获模式也称为不可变借用捕获

2. 闭包内修改变量

fn main() {
    let mut word = String::from("Hello");
    
// mutable closure let mut print_str = || { // value of word is changed here word.push_str(" World!"); println!("word = {}", word); };
// cannot immutable borrow because the variable is borrowed as mutable inside the closure // println!("length of word = {}", word.len()); print_str(); // can immutable borrow because the closure has been already used println!("length of word = {}", word.len()); }

输出

word = Hello World!
length of word = 12

在这里,变量 word 在闭包 print_str 中被 word.push_str("World!"); 修改。因此,我们必须使变量 word 和闭包变量 print_str 都可变。这意味着除非使用闭包,否则不能存在 word 变量的其他引用。

这种捕获模式也称为可变借用捕获

3. 闭包内移动变量

fn main() {
    let word = String::from("Hello");

// immutable closure let print_str = || { // word variable is moved to a new variable let new_word = word; println!("word = {}", new_word); };
print_str(); // cannot immutable borrow because word variable has moved inside closure // println!("length of word = {}", word.len()); }

输出

word = Hello

在这里,我们将变量 word 移动到闭包内部的一个新变量 new_word 中。由于变量被移动了,除了在闭包内部使用它之外,我们不能在其他任何地方使用它。

这种捕获模式也称为移动捕获


常见问题

Rust 中的函数和闭包有什么区别?

Rust 中函数和闭包的主要区别在于,闭包可以捕获其作用域中的值(环境捕获),而函数的设计则不能。

此外,我们在 Rust 中创建闭包和函数的方式也有一些不同。例如,

// function to add numbers
fn add_numbers(a: i32, b: i32) {
    let sum = a + b;
    
    println!("Sum: {}", sum);
}

// closure to add numbers
let add_numbers = |a: i32, b: i32| {
    let sum = a + b;
    
    println!("Sum: {}", sum);
};
如何在 Rust 中将闭包用作函数参数?

让我们看一个将闭包作为函数参数的示例。

// function that takes in a closure
fn add_one<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
    return f(x) + 1;
}

fn main() {
    // closure to square a variable
    let square = |x: i32| { x * x };
    
    // call add_one function with closure as the second argument
    let result = add_one(5, square);
    
    println!("result = {}", result);
}

输出

result = 26

在这里,函数 add_one 将闭包作为第二个参数。我们首先运行返回整数平方 |x: i32| { x * x } 的闭包,然后在 add_one 函数内部将 1 加到闭包的结果上。

return f(x) + 1;

因此,当我们传递 5 作为第一个参数和 square 闭包作为第二个参数时,结果是 26,即 5 * 5 + 1

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战