简体   繁体   English

如何编写需要一部分函数的函数?

[英]How to write a function that takes a slice of functions?

I am trying to write a function that takes a slice of functions. 我正在尝试编写一个需要一部分函数的函数。 Consider the following simple illustration : 考虑下面的简单说明

fn g<P: Fn(&str) -> usize>(ps: &[P]) { }

fn f1() -> impl Fn(&str) -> usize { |s: &str| s.len() }
fn f2() -> impl Fn(&str) -> usize { |s: &str| s.len() }

fn main() {
    g(&[f1(), f2()][..]);
}

It fails to compile: 它无法编译:

error[E0308]: mismatched types
 --> src/main.rs:6:15
  |
6 |     g(&[f1(), f2()][..]);
  |               ^^^^ expected opaque type, found a different opaque type
  |
  = note: expected type `impl for<'r> std::ops::Fn<(&'r str,)>` (opaque type)
             found type `impl for<'r> std::ops::Fn<(&'r str,)>` (opaque type)

Is there any way to do this? 有什么办法吗?

Your problem is that every element of the array must be of the same type, but the return of a function declared as returning impl Trait is an opaque type , that is an unspecified, unnamed type, that you can only use by means of the given trait. 您的问题是数组的每个元素必须具有相同的类型,但是声明为returning impl Trait的函数的返回是不透明的类型 ,即未指定的,未命名的类型,您只能通过给定的方式使用特征。

You have two functions that return the same impl Trait but that does not mean that they return the same type. 您有两个函数返回相同的impl Trait但这并不意味着它们返回相同的类型。 In fact, as your compiler shows, they are different opaque types, so they cannot be part of the same array. 实际上,如编译器所示,它们是不同的不透明类型,因此它们不能属于同一数组。 If you were to write an array of values of the same type, such as: 如果要编写一个具有相同类型的值的数组,例如:

    g(&[f1(), f1(), f1()]);

then it would work. 那就行了。 But with different functions, there will be different types and the array is impossible to build. 但是使用不同的功能,将有不同的类型,并且无法构建数组。

Does that mean there is no solution for your problem? 这是否意味着您的问题没有解决方案? Of course not! 当然不是! You just have to invoke dynamic dispatch. 您只需要调用动态调度即可。 That is you have to make your slice of type &[&dyn Fn(&str) -> usize] . 那就是您必须使&[&dyn Fn(&str) -> usize]类型的切片。 For that you need to do two things: 为此,您需要做两件事:

  1. Add a level of indirection: dynamic dispatching is always done via references or pointers ( &dyn Trait or Box<dyn Trait> instead of Trait ). 添加一个间接级别:动态分配总是通过引用或指针( &dyn TraitBox<dyn Trait>而不是Trait )完成。
  2. Do an explicit cast to the &dyn Trait to avoid ambiguities in the conversion. &dyn Trait进行显式转换,以避免转换中的歧义。

There are many ways to do the cast: you can cast the first element of the array, or you can declare the temporary variables, or give the slice a type. 有很多方法可以进行转换:可以转换数组的第一个元素,也可以声明临时变量,或为切片指定类型。 I prefer the latter, because it is more symmetric. 我更喜欢后者,因为它更加对称。 Something like this: 像这样:

fn main() {
    let fns: &[&dyn Fn(&str) -> usize] = 
        &[&f1(), &f2()];
    g(fns);
}

Link to a playground with this solution. 使用此解决方案链接到游乐场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何编写带迭代器的 Rust 函数? - How to write a Rust function that takes an iterator? 如何在 Python 中编写一个没有 Pandas 的文件的函数? - How to write a function which takes files without Pandas in Python? 写一个 function 需要 2 个字符串 arguments - write a function that takes 2 string arguments 如何编写仅将枚举的一个变体作为输入的函数 - how to write a function that only takes one variant of the enum as input 如何编写一个 function 以文件名作为 Python 中的参数? - How to write a function that takes in the name of a file as the argument in Python? 如何编写一个模板函数,它接受一个数组和一个指定数组大小的int - How to write a template function that takes an array and an int specifying array size 如何编写一个包含2个字符串的函数,并将它们添加到相应数组的BEGINNING中 - how to write a function that takes 2 strings, and add them to the BEGINNING of the respective arrays 如何编写一个带有默认参数的lambda的泛型函数? - How to write a generic function that takes a lambda with a default argument? 如何编写带有任意数量参数的PHP函数? - How can I write a PHP function that takes an arbitrary number of parameters? 如何在Powershell中编写函数以创建函数 - How to write a function to create functions in Powershell
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM