gpt4 book ai didi

rust - 如何将 Rust 函数作为参数传递?

转载 作者:行者123 更新时间:2023-11-29 07:40:06 26 4
gpt4 key购买 nike

我可以将函数作为参数传递吗?如果不是,什么是好的替代方案?

我尝试了一些不同的语法,但我没有找到正确的语法。我知道我可以做到这一点:

fn example() {
let fun: fn(value: i32) -> i32;
fun = fun_test;
fun(5i32);
}

fn fun_test(value: i32) -> i32 {
println!("{}", value);
value
}

但这并不是将函数作为参数传递给另一个函数:

fn fun_test(value: i32, (some_function_prototype)) -> i32 {
println!("{}", value);
value
}

最佳答案

当然可以:

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, &times2);
}

因为这是 Rust,你必须考虑 ownership and lifetime of the closure .

长话短说;基本上有 3 种类型的闭包(可调用对象):

  1. Fn:它不能修改它捕获的对象。
  2. FnMut:它可以修改它捕获的对象。
  3. FnOnce:最受限制。只能调用一次,因为调用时会消耗自身及其捕获。

参见 When does a closure implement Fn, FnMut and FnOnce?了解更多详情

如果您使用像闭包这样的简单的指向函数的指针,那么捕获集是空的并且您有 Fn 风格。

如果您想做更多花哨的事情,那么您将不得不使用 lambda 函数。

在 Rust 中有适当的函数指针,它们的工作方式与 C 中的函数一样。它们的类型例如是 fn(i32) -> i32Fn(i32) -> i32FnMut(i32) -> i32FnOnce(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;
//static dispatch
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
//dynamic dispatch
fun_test_dyn(5, &times2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
//C-like pointer to function
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x); //ok: empty capture set
fun_test_ptr(5, |x| y*x); //error: expected fn pointer, found closure
}

关于rust - 如何将 Rust 函数作为参数传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36390665/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com