这个问题是在这question个问题之后提出的.

作为Rust的新手,我正在try 了解函数指针(FN)的初始化方式.以下是对我正在编写的应用程序的简短且简单得多的描述.

Controller是用route: i32值初始化的.稍后,该值可以被修改,并且所有旧值被存储在列表中,作为history of changes.

下面是一个‘lib.rs’示例内容:

use futures::future;
use random_number::random;



pub struct Controller {
    pub route: i32,
    pub running_history_modified_routes: Vec<i32>
}

impl Controller {

     // a 'route' is initialized with an integer
     pub fn new(p: i32) -> Controller {
         Controller { route: p, running_history_modified_routes: Vec::new()}
     }

     // Subsequently, the 'route' may get a new value.
     // Here, we are generating a random new value and storing that in
     // vector, as history of changes to route.
     pub fn compute_a_new_route (&mut self, using_seed: i32) -> &mut Controller {

            // My confusion is around this initialization!
            let as_function_pointer: fn(i32) -> i32 = free_function_generate_random_route_value;

            let a_fresh_route = self.get_a_route_afresh(using_seed,as_function_pointer);
            self.running_history_modified_routes.push(a_fresh_route);
            self

     }

     fn get_a_route_afresh(&self, seed_as_higher_limit: i32, f:fn(i32) -> i32) -> i32 {
             f(seed_as_higher_limit)
     }

     fn method_generate_random_route_value(&self,seed_as_higher_limit: i32) -> i32 {
         random!(0 as i32, seed_as_higher_limit)
     }

    fn assoc_function_generate_random_route_value(seed_as_higher_limit: i32) -> i32 {
        random!(0 as i32, seed_as_higher_limit)
    }
}

fn free_function_generate_random_route_value(seed_as_higher_limit: i32) -> i32 {
    random!(0 as i32, seed_as_higher_limit)
}

fn get_a_route_afresh(..)接收函数指针并调用它以获得新的路由值(在本例中,这当然是一个随机数:-).

我有三个不同的候选函数指针(在上面的代码中注释):

  • 控制器的实现方法method_generate_random_route_value
  • 控制器的关联功能assoc_function_generate_random_route_value
  • 模块的自由功能free_function_generate_random_route_value

我的理解是,它们中的每一个都可以用来在调用same way!但是,当我这样做时,编译器不同意:

let as_function_pointer: fn(i32) -> i32 = self.method_generate_random_route_value;

他告诉我:

error[E0615]: attempted to take value of method `method_generate_random_route_value` on type `&mut Controller`
  --> src/lib.rs:20:60
   |
20 |             let as_function_pointer: fn(i32) -> i32 = self.method_generate_random_route_value;
   |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method, not a field
   |
help: use parentheses to call the method
   |
20 |             let as_function_pointer: fn(i32) -> i32 = self.method_generate_random_route_value(_);
   |                                                                                              +++

当然,当我使用关联或自由函数时,编译器和我都很高兴.

当需要函数指针时,我在(impl)方法的适用性方面错过了什么?

下面是Cargo.toml条:

[package]
name = "FutureExperiment"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
random-number = "0.1.8"


[lib]
name="function_pointers_experiment"
path="src/lib.rs"

推荐答案

绑定self的函数不是函数指针.函数指针fn(带有小写‘f’)是指向顶层Rust函数的指针,该函数does not靠近任何变量.一旦你想结束变量(甚至self),你不再有一个函数指针.相反,您有一个闭包Fn(或FnOnceFnMut,这取决于您关闭变量的方式).顶级函数是函数指针,而关联的函数(没有self绑定)实际上只是另一个名称的顶级函数.

如果你想接受任何callable个物体,FnMut是一个很好的起点.如果需要同时调用Fn(使用大写‘F’)(因为Fn不允许接受可变引用,因此同时在多个地方共享是安全的),则使用Fn;如果需要取得某些只能使用一次的值的所有权,则使用FnOnce.函数指针的类型fn主要用于需要指向某个函数的实际具体指针的低级技术,例如在与不知道闭包是什么的C代码接口时.

Rust相关问答推荐

为什么在Rust struct 中只允许最后一个字段具有动态大小的类型

rust 蚀将动力特性浇到混凝土 struct 上是行不通的

抽象RUST中的可变/不可变引用

在函数内定义impl和在函数外定义impl的区别

在Rust中宏的表达式中提取对象

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

创建Rust中元对象协议的动态对象 Select /重新分配机制

正则表达式中的重叠匹配?(铁 rust 正则式发动机)

确保参数是编译时定义的字符串文字

将 &str 或 String 保存在变量中

将引用移动到线程中

pyO3 和 Panics

为什么 File::read_to_end 缓冲区容量越大越慢?

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

如何获得对数组子集的工作可变引用?

将文件的第一行分别读取到文件的其余部分的最有效方法是什么?

相交着色器从 SSBO 中读取零

在使用大型表达式时(8k 行需要一小时编译),是否可以避免 Rust 中的二次编译时间?

Rust 生命周期:不能在方法内重新borrow 可变字段

在特征中返回一个 Self 类型的值