如何编写 returns 本身的函数?

How do I write a function that returns itself?

我想做的是一个函数,return本身,所以我可以这样称呼它:

foo()()...()

在 C# 中,它将通过委托完成:

delegate SelfFunc SelfFunc();

static void Main() {
    SelfFunc foo = null;
    foo = () => {
        return foo;
    };
    foo()()...();
}

预料到诸如“为什么要实现这种愚蠢的行为?”之类的问题:我想使用单个函数继续调用以一种非常奇怪的方式对数字求和:foo(1)(2)(3)() = 6,但在这个问题中我只想知道如何 return 自行运作。我在 C# 中制作的此方法的示例实现。这只是为了好玩和学习 Rust:

static int sum = 0;
delegate dynamic InfFunc(int i = int.MaxValue);
 
static void InfFuncTest() {
    InfFunc f = null;
    f = (int i) => {
        if(i == int.MaxValue) {
            return sum;
        }
        sum += i;
        return f;
    };
 
    var g = f;
    var value = g(1)(2)(3)();
    Console.WriteLine(value);
}

一个 returns 本身可以在 nightly 上实现的功能。

首先您需要启用功能 unboxed_closuresfn_traits

然后你可以定义一个结构,当调用时,returns self。完整代码如下所示:

#![feature(unboxed_closures, fn_traits)]

struct SelfFunc;

impl FnOnce<()>  for SelfFunc {
    type Output = SelfFunc;

    extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
        self
    }
}

然后您可以根据需要多次调用该函数:

fn main() {
  let f = SelfFunc;
  f()()()()()();
}

根据@cameron1024 的回答,您可以使用特征“重载”,但是您将需要 2 个结构来正确处理 foo()(此处称为 Add)的空情况,而不返回任何参数0.

#![feature(unboxed_closures, fn_traits)]

struct Add;

impl FnOnce<(u32,)>  for Add {
    type Output = AddImpl;

    extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
        AddImpl(args.0)
    }
}

impl FnOnce<()>  for Add {
    type Output = u32;

    extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
        0
    }
}

struct AddImpl(u32);

impl FnOnce<()>  for AddImpl {
    type Output = u32;

    extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
        self.0
    }
}

impl FnOnce<(u32,)>  for AddImpl {
    type Output = AddImpl;

    extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
        Self(self.0 + args.0)
    }
}


fn main() {
    dbg!( Add(1)(2)(3)() );
    dbg!( Add() );
}

Playground

如果您不关心无参数 foo() 要求,您可以将 Add 改为元组结构并删除 AddImpl:

#![feature(unboxed_closures, fn_traits)]

struct Add(u32);

impl FnOnce<(u32,)>  for Add {
    type Output = Add;

    extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
        Add(self.0 + args.0)
    }
}

impl FnOnce<()>  for Add {
    type Output = u32;

    extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
        self.0
    }
}

fn main() {
    dbg!( Add(1)(2)(3)() );
    //dbg!( Add() ); // doesn't compile
}

Playground

虽然我应该注意到这可能不是一个好主意,但使用 slice/iterator 可能会导致更清晰的代码:

fn main() {
    dbg!([1, 2, 3].iter().copied().sum::<u32>());
}

Playground