You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rust中如何存储异构函数组成的延迟执行调用链?

实现方案

Rust作为静态类型语言,无法直接用Vec存储类型异构的函数,你可以根据场景选择以下两种方案实现需求:

方案1:编译期类型安全的零开销实现

这种方案通过递归泛型结构体实现,所有类型检查在编译期完成,无任何运行时开销,适合函数链结构在编译期就可以确定的场景。

核心实现代码

// 终止标记:代表函数链的末尾
struct Nil;

// 函数链节点:存储当前函数和下一段链
struct Cons<S, T, N> {
    func: fn(S) -> T,
    next: N,
}

// 调用trait:统一不同节点的调用行为
trait Call<Input> {
    type Output;
    fn call(&self, input: Input) -> Self::Output;
}

// 终止节点的调用实现:直接返回输入值
impl<I> Call<I> for Nil {
    type Output = I;
    fn call(&self, input: I) -> Self::Output {
        input
    }
}

// 普通节点的调用实现:先执行当前函数,再把输出传给下一段链
impl<S, T, N, O> Call<S> for Cons<S, T, N>
where
    N: Call<T, Output = O>,
{
    type Output = O;
    fn call(&self, input: S) -> Self::Output {
        let next_input = (self.func)(input);
        self.next.call(next_input)
    }
}

// 扩展方法:方便链式拼接函数
impl<S, T, N> Cons<S, T, N> {
    fn then<U>(self, func: fn(T) -> U) -> Cons<T, U, Self> {
        Cons { func, next: self }
    }
}

// 构造函数链的入口
fn func_chain<S, T>(func: fn(S) -> T) -> Cons<S, T, Nil> {
    Cons { func, next: Nil }
}

使用示例

fn main() {
    // 构造函数链:i32 -> String -> u8 -> String -> i32
    let chain = func_chain(|x: i32| x.to_string())
        .then(|s| s.parse::<u8>().unwrap())
        .then(|n| n.to_string())
        .then(|s| s.parse::<i32>().unwrap());
    
    // 执行调用
    let res = chain.call(123);
    println!("执行结果:{}", res); // 输出 123
}

这种方案下函数链的类型会在编译期自动推导,任何输入输出不匹配的错误都会在编译期被捕获,完全不需要运行时类型检查。

方案2:运行时动态可修改的类型擦除实现

如果你需要在运行时动态添加/删除函数,可以通过类型擦除的方式实现,会有少量运行时开销,且需要处理类型转换失败的情况:

use std::any::Any;

struct DynFuncChain {
    funcs: Vec<Box<dyn FnOnce(Box<dyn Any>) -> Result<Box<dyn Any>, &'static str>>>,
}

impl DynFuncChain {
    fn new() -> Self {
        Self { funcs: Vec::new() }
    }

    fn add<S: 'static, T: 'static>(&mut self, func: fn(S) -> T) {
        self.funcs.push(Box::new(move |input: Box<dyn Any>| {
            let s = input.downcast::<S>().map_err(|_| "类型转换失败")?;
            Ok(Box::new(func(*s)))
        }));
    }

    fn call<I: 'static, O: 'static>(self, input: I) -> Result<O, &'static str> {
        let mut res: Box<dyn Any> = Box::new(input);
        for func in self.funcs {
            res = func(res)?;
        }
        res.downcast::<O>().map(|o| *o).map_err(|_| "最终结果类型不匹配")
    }
}

// 使用示例
fn main() {
    let mut chain = DynFuncChain::new();
    chain.add(|x: i32| x.to_string());
    chain.add(|s: String| s.parse::<u8>().unwrap());
    chain.add(|n: u8| n.to_string());
    chain.add(|s: String| s.parse::<i32>().unwrap());

    let res = chain.call(123).unwrap();
    println!("执行结果:{}", res); // 输出 123
}

内容的提问来源于stack exchange,提问作者Migwell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 04:36:05