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

如何编写可返回自身的函数,支持foo()()...()形式的链式调用?

Rust实现自返回函数与链式调用求和

核心思路

Rust的类型系统不支持直接定义递归的函数类型,也没有C#的dynamic动态类型绕过检查,因此需要通过newtype包装结构体的方式实现自返回逻辑,求和场景下我们还会把累加值存在结构体内部,避免使用全局可变变量。

1. 基础版:无参数自返回函数

如果仅需要实现foo()()...()的无限链式调用,有两种实现方式:

(1)Nightly版本(支持()直接调用)

需要启用Rust不稳定特性,实现Fn系列trait:

// 顶部开启特性
#![feature(fn_traits, unboxed_closures)]

#[derive(Copy, Clone)]
struct SelfFunc(fn() -> SelfFunc);

// 实现FnOnce/FnMut/Fn trait支持()调用
impl FnOnce<()> for SelfFunc {
    type Output = SelfFunc;
    extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
        self.0()
    }
}

impl FnMut<()> for SelfFunc {
    extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
        self.0()
    }
}

impl Fn<()> for SelfFunc {
    extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
        self.0()
    }
}

fn main() {
    let foo = SelfFunc(|| foo);
    // 支持无限链式调用
    foo()()()()();
}

(2)稳定版兼容实现

不需要不稳定特性,通过自定义方法调用即可:

#[derive(Copy, Clone)]
struct SelfFunc(fn() -> SelfFunc);

impl SelfFunc {
    fn call(self) -> Self {
        self.0()
    }
}

fn main() {
    let foo = SelfFunc(|| foo);
    foo.call().call().call();
}

2. 进阶版:链式调用求和

完全实现你要的foo(1)(2)(3)() = 6的效果:

Nightly版本(原生支持()调用)

#![feature(fn_traits, unboxed_closures)]

#[derive(Copy, Clone)]
struct SumFunc {
    sum: i32,
}

// 处理传入整数的调用:累加后返回自身
impl FnOnce<(i32,)> for SumFunc {
    type Output = SumFunc;
    extern "rust-call" fn call_once(self, args: (i32,)) -> Self::Output {
        SumFunc { sum: self.sum + args.0 }
    }
}

impl FnMut<(i32,)> for SumFunc {
    extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> Self::Output {
        self.sum += args.0;
        *self
    }
}

impl Fn<(i32,)> for SumFunc {
    extern "rust-call" fn call(&self, args: (i32,)) -> Self::Output {
        SumFunc { sum: self.sum + args.0 }
    }
}

// 处理无参调用:返回最终累加结果
impl FnOnce<()> for SumFunc {
    type Output = i32;
    extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
        self.sum
    }
}

impl FnMut<()> for SumFunc {
    extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
        self.sum
    }
}

impl Fn<()> for SumFunc {
    extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
        self.sum
    }
}

fn main() {
    let foo = SumFunc { sum: 0 };
    let res = foo(1)(2)(3)();
    assert_eq!(res, 6);
    println!("{}", res); // 输出6
}

稳定版兼容实现

用自定义方法替代原生()调用,不需要依赖不稳定特性:

#[derive(Copy, Clone)]
struct SumFunc {
    sum: i32,
}

impl SumFunc {
    fn new() -> Self {
        SumFunc { sum: 0 }
    }

    // 传入数字累加,返回新的实例
    fn add(self, num: i32) -> Self {
        SumFunc { sum: self.sum + num }
    }

    // 结束调用,返回结果
    fn result(self) -> i32 {
        self.sum
    }
}

fn main() {
    let foo = SumFunc::new();
    let res = foo.add(1).add(2).add(3).result();
    assert_eq!(res, 6);
}

补充说明

C#中可以直接用递归委托+dynamic类型实现的核心是运行时类型检查,Rust为了保证内存安全和零成本抽象,所有类型必须在编译期确定,因此必须通过newtype包装的方式构造合法的递归类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 11:54:04