rust - 创建一个具有可交换功能的结构

标签 rust closures constants

我想要一个结构,它包含一个由该结构的用户设置的函数。我想到了这样的事情:

pub struct MyStruct {
    some_function: Fn(f64) -> f64
}

然后我想定义一组可以在创建 MyStruct 实例时选取的常量。我这样试过:

pub const SIGMOID: Fn(f64) -> f64 = |x| 1.0 / (1.0 + E.powf(x));

我收到一个编译错误,即 Fn(f64) -> f64 在编译时没有已知的大小,并且出现了使用 dyn 的警告关键词。我不想使用 dyn 关键字,因为会降低性能。我是否必须使用 Box 将该常量放在堆上,或者是否有更轻量级的方法来执行此操作?我认为将其存储在堆上也会降低性能,还是我弄错了?

最佳答案

引用Fn trait docs :

This trait (Fn) is not to be confused with function pointers (fn).

函数指针不允许您以类似闭包的方式拥有状态。如果您使用的是 sigmoid 函数之类的东西,它是在没有状态的情况下定义的,您可以使用它。如果您使用带状态的闭包,您需要具有某种形式的动态调度或泛型类型,因为您无法命名闭包的类型。

例如,使用 fn 指针:

struct Foo {
    my_func: fn(f64) -> f64
}

或者使用动态调度和引用:

struct Foo<'a> {
    my_func: &'a dyn Fn(f64) -> f64,
}

或者具有可变状态:

struct Foo<'a> {
    my_func: &'a mut dyn FnMut(f64) -> f64,
}

没有生命周期:

struct Foo {
   my_func: Box<dyn FnMut(f64) -> f64>
}

I think there's gonna be a performance penalty when storing it on the heap too or am I mistaken here?

是的,由于通过 vtable 的双重间接性,动态调度经常会受到惩罚。 我相信,我不确定,由于缺乏单态化,也会受到惩罚。但是,除非它们是可量化的,否则这些都不重要。

pub const SIGMOID: Fn(f64) -> f64 = |x| 1.0 / (1.0 + E.powf(x));

这可以变成

pub const SIGMOID: fn(f64) -> f64 = |x| 1.0 / (1.0 + E.powf(x));

fn pointers实现所有 Fn* 特性:

In addition, function pointers of any signature, ABI, or safety are Copy, and all safe function pointers implement Fn, FnMut, and FnOnce. This works because these traits are specially known to the compiler.

关于rust - 创建一个具有可交换功能的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58049565/

相关文章:

c# - 闭包和 java 匿名内部类

rust - 如何在不使用匹配的情况下从元组设置结构成员?

types - 我如何在 Rust 中获得 `std::any::TypeId::of` 超过 `T` 、 `&T` 和 `&mut` T 的相同结果?

javascript - 如何封装对象属性以便以前的对象不被接管? (原型(prototype)/闭合。)

c++ - 有没有像 bits_in_byte (8) 这样的常量?

c - "static const"vs "#define"vs "enum"

java - java 或 java 库中是否有语言代码常量?

x/y 坐标的排序向量

rust - 如何将 Vec<Result<T, E>> 转换为 Result<Vec<T>, E>?

java - 从堆转储中的错误名称中查找 Java lambda