如何编写 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_closures
和 fn_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() );
}
如果您不关心无参数 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
}
虽然我应该注意到这可能不是一个好主意,但使用 slice/iterator 可能会导致更清晰的代码:
fn main() {
dbg!([1, 2, 3].iter().copied().sum::<u32>());
}
我想做的是一个函数,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_closures
和 fn_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() );
}
如果您不关心无参数 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
}
虽然我应该注意到这可能不是一个好主意,但使用 slice/iterator 可能会导致更清晰的代码:
fn main() {
dbg!([1, 2, 3].iter().copied().sum::<u32>());
}