Generics 创建从任何类型到任何其他类型的闭包向量

Generics 创建从任何类型到任何其他类型的闭包向量,generics,rust,Generics,Rust,我试图创建一个函数向量,其思想是第一个函数的输出将通过管道传输到第二个函数的输入,等等 我很难理解如何(如果可能的话)将其编码到锈型系统中。我尝试使用泛型,但遇到了问题,因为泛型希望函数向量中的每个元素的输入和输出总是相同的 例如,函数一可以是i32->String,函数二String->bool和函数三bool->f64 我的尝试: fn main() { let mut funcs: Vec<Box<Fn(i32) -> i32>> = Vec::new

我试图创建一个函数向量,其思想是第一个函数的输出将通过管道传输到第二个函数的输入,等等

我很难理解如何(如果可能的话)将其编码到锈型系统中。我尝试使用泛型,但遇到了问题,因为泛型希望函数向量中的每个元素的输入和输出总是相同的

例如,函数一可以是
i32->String
,函数二
String->bool
和函数三
bool->f64

我的尝试:

fn main() {
    let mut funcs: Vec<Box<Fn(i32) -> i32>> = Vec::new();

    funcs.push(Box::new(|a| a * 2));
    funcs.push(Box::new(|b| b * 3));

    // This won't work since it's not a Fn(i32) -> i32
    funcs.push(Box::new(|c| String::from(c)));

    // How can I create a vec of Fn(anything) -> anything where the anythings can be different for every item in the vector?
}
fn main(){
让mut funcs:Vec>=Vec::new();
功能推送(框::新建(|a | a*2));
函数推送(框::新建(| b | b*3));
//这不起作用,因为它不是Fn(i32)->i32
push函数(Box::new(| c | String::from(c));
//如何创建Fn(anythings)->向量中每个项目的anythings都不同的向量?
}
我开始认为,Rust中唯一可能的方法是使用宏创建具有特定数量元素的结构。

您可以在
框中使用trait,但是:

  • 如果类型不匹配,则会出现运行时错误,而不是编译时错误
  • 性能可能会很差


如果您实际等待了很多时间,例如等待网络数据(而不是实际需要CPU时间),您可能需要查看板条箱,尤其是。

为什么需要将其存储在
Vec
中?这似乎是这里冲突的核心
Vec
是一个定义相同类型的项目列表,不适合您所需的内容。@loganfsmyth我可以使用其他类型的集合吗?我希望一个结构有一个函数集合如果你的目标是创建一个函数链,这些函数一起提供,你可以返回一个新函数,将两个函数组合在一起,完全避免集合。对于组合的函数链来说,集合不是一个好的数据结构。如果您的目标是收集并按顺序调用每个函数,那么最好只是使结构存储成为调用链的函数,因此,结构只需知道完整链的输入和输出类型。从任何类型到任何其他类型-以及当输出与后续输入不匹配时会发生什么情况?我觉得你最好先问一下你的问题,然后再问细节。对我来说,这感觉有点像是一场灾难。我理解你想要解决的问题,但Vec并不是解决这个问题的好方法。对于您提出的特定问题,您可以使用
Any
,在这里找到答案,但对于问题的真正解决方案,答案是不要使用Vec。我个人认为事件循环很容易遵循,这将解决您的真正目标,但可能有很多方法来考虑这一点。
use std::any::Any;

pub type FnAnyToAny = Fn(Box<Any>) -> Box<Any>;

pub fn make_any_to_any<I, O, F>(f: F) -> Box<FnAnyToAny>
where
    I: 'static,
    O: 'static,
    F: Fn(I) -> O + 'static,
{
    Box::new(move |i: Box<Any>| -> Box<Any> {
        let i: Box<I> = Box::<Any + 'static>::downcast(i).expect("wrong input type");
        Box::new(f(*i))
    })
}

pub fn run_all_any<I, O>(funcs: &Vec<Box<FnAnyToAny>>, i: I) -> O
where
    I: 'static,
    O: 'static,
{
    let i: Box<Any> = Box::new(i);
    let o = funcs.iter().fold(i, |acc, f| f(acc));
    let o: Box<O> = Box::<Any + 'static>::downcast(o).expect("wrong output type");
    *o
}

fn main() {
    let mut funcs: Vec<Box<FnAnyToAny>> = Vec::new();

    funcs.push(make_any_to_any(|a: i32| a * 2));
    funcs.push(make_any_to_any(|b: i32| b * 3));

    funcs.push(make_any_to_any(|c: i32| format!("{}", c)));

    println!("{:?}", run_all_any::<i32, String>(&funcs, 4));
}
extern crate rayon;
use rayon::prelude::*;

fn main() {
    let input = vec![1, 2, 3, 4];

    // without parallel processing you'd start with:
    // let output = input.into_iter()
    let output = input
        .into_par_iter()
        .map(|a| a * 2)
        .map(|b| b * 3)
        .map(|c| format!("{}", c))
        .collect::<Vec<_>>();

    println!("{:?}", output);
}