rust - 动态选择要调用的函数,无需中间变量

标签 rust

我正在尝试根据条件选择要调用的函数。我想将该函数存储在一个变量中,以便稍后可以再次调用它而无需携带条件。这是一个最小的工作示例:

fn foo() {
    println! ("Foo");
}
fn bar() {
    println! ("Bar");
}

fn main() {
    let selector = 0;

    let foo: &Fn() = &foo;
    let bar: &Fn() = &bar;
    let test = match selector {
        0 => foo,
        _ => bar
    };
    test();
}

我的问题是:是否可以去掉中间变量?我试过简单地删除它们:

fn foo() {
    println! ("Foo");
}
fn bar() {
    println! ("Bar");
}

fn main() {
    let selector = 0;

    let test = match selector {
        0 => &foo as &Fn(),
        _ => &bar as &Fn()
    };
    test();
}

但是随后借用检查器提示说借用的值只在匹配结束之前有效(顺便说一句,为什么?函数是'static 无论如何应该有效到时间结束) .我还尝试通过使用 &foo as &'static Fn() 使 'static 生命周期显式化,但这也不起作用。

最佳答案

如果您只需要使用静态函数而不是闭包,则以下方法有效:

fn foo() {
    println!("Foo");
}

fn bar() {
    println!("Bar");
}

fn main() {
    let selector = 0;

    let test: fn() = match selector {
        0 => foo,
        _ => bar
    };

    test();
}

(试穿playground)

这里我使用了函数类型而不是函数特征。

借来的trait对象不起作用的原因大概有以下几点。任何特征对象都是一个胖指针,由指向某个值的指针和指向虚拟表的指针组成。当 trait 对象从闭包中创建时,一切都很清楚——值将由闭包本身表示(在内部是包含所有捕获变量的结构的实例)并且虚拟表将包含指向实现的指针编译器生成的相应 Fn*() 特征,其主体将是闭包主体。

然而,对于函数,事情就不是那么清楚了。从中创建特征对象没有值(value),因为函数本身应该对应于 Fn() 特征的实现。因此,rustc 可能会生成一个空结构并为其实现 Fn(),并且此实现直接调用静态函数(不是实际的 Rust,而是接近的东西):

struct SomeGeneratedStructFoo;

impl Fn<()> for SomeGeneratedStructFoo {
    type Output = ();
    fn call(&self, args: ()) -> () {
        foo();
    }
}

因此,当通过 fn foo() 创建特征对象时,实际上会引用一个类型为 SomeGeneratedStructFoo 的临时值。然而,这个值是在匹配中创建的,并且只从匹配中返回对它的引用,因此这个值的生命周期不够长,这就是错误的原因。

关于rust - 动态选择要调用的函数,无需中间变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32885446/

相关文章:

multithreading - 在 amd64 上拆分堆栈是不必要的

rust - 为什么每种情况下读取的字节数不同?

rust - 基于特征标志有条件地推导

multithreading - 有没有办法让 Rust 闭包只将一些变量移入其中?

csv - 如何迭代/流式传输 gzip 文件(包含单个 csv)?

c - 生成 C header 时隐藏 Rust 库的私有(private)字段

rust - 如何选择退出运行文档测试?

rust - 当迭代器使用容器时,是否可以从循环中返回容器?

rust - 是否不可能对使用智能指针(如 Box、Rc 或 Arc)的递归数据类型进行嵌套匹配?

types - 这个 Rust 函数返回的迭代器类型是什么?