在 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 变量。
程序的工作原理如下,

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
在上面的示例中,我们创建了一个接受两个参数:x
和 y
的闭包。在闭包内部,我们将 x
和 y
相加,并将结果赋给 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. 闭包内不修改变量
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 中创建闭包和函数的方式也有一些不同。例如,
// 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);
};
让我们看一个将闭包作为函数参数的示例。
// 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
。