你当然可以:
fn fun_test(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
fun_test(5, ×2);
}
由于这是Rust,因此您必须考虑closure的所有权和生存期。
TL; DR; 基本上有3种类型的闭包(可调用对象):
Fn
:它不能修改捕获的对象。
FnMut
:它可以修改捕获的对象。
FnOnce
:最受限制。只能被调用一次,因为调用时它将消耗自身和捕获。
请参阅闭包何时实现Fn,FnMut和FnOnce?更多细节
如果您使用的是简单的指向函数的指针(如闭包),则捕获集为空并且具有Fn
味道。
如果您想做更多花哨的东西,那么您将不得不使用lambda函数。
在Rust中,有适当的指向函数的指针,这些指针的工作方式与C语言中的函数相同。例如,它们的类型fn(i32) -> i32
。的Fn(i32) -> i32
,FnMut(i32) -> i32
而FnOnce(i32) -> i32
实际上是特征。指向函数的指针始终实现这三个函数,但是Rust也具有闭包,闭包可以转换为也可以不转换为函数的指针(取决于捕获集是否为空),但是它们确实实现了某些这些特性。
因此,例如,可以扩展上面的示例:
fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
let y = 2;
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
fun_test_dyn(5, ×2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x);
fun_test_ptr(5, |x| y*x);
}