如何在Rust中实现多层次的curring函数? [英] How to implement a multiple level currying function in Rust?

查看:48
本文介绍了如何在Rust中实现多层次的curring函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试实现类似于这行得通,但是如果我再加一级的话:

This works, but if I add one level deeper:

fn add(x: i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
    return move |y: i32| {
        return move |z: i32| {
            x + y + z
        }
    };
}

fn main() {
    let add5 = add(5);
    let add5_10 = add5(10);
    println!("Call closure: {}", add5_10(6));
}

编译器不接受并告诉我:

Compiler do not accept and tell me:

error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
 --> src/main.rs:7:35
  |
7 | fn add(x: i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
  |                                   ^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

为什么不允许这样做?有没有一种更好的方法可以在Rust中实现curring?

Why is this not allowed? Is there a better way to implement currying in Rust?

推荐答案

impl特性语法只能在函数签名的参数位置或返回位置使用.两者都很好:

impl Trait syntax can only be used in argument position or return position of a function signature. Both of these are fine:

fn takes_fn(fn_arg: impl Fn(i32) -> i32) {}

fn returns_fn() -> impl Fn(i32) -> i32 {
  |x| x
}

但是这些都不起作用:

fn takes_fn(fn_arg: impl Fn(i32) -> impl Fn(i32) -> i32) {}

fn returns_fn() -> impl Fn(i32) -> impl Fn(i32) -> i32 {
  |x| x
}

因为第二个嵌套的 impl Trait 不再位​​于参数或返回位置,但现在已成为参数或返回类型签名的一部分,这是不允许的.基本上,无论您将其放置在何处,多个嵌套 impl Trait 都将永远无法工作,并且始终会出现相同的编译错误.

Because the second nested impl Trait is no longer in argument or return position but is now part of the argument or return type's signature, which is not somewhere where it is allowed. Basically, multiple nested impl Traits will never work regardless of where you place them and you'll always get the same compile error.

好消息是这不会阻止您完成要完成的任务,因为 impl Trait 只是语法糖,它的使用是可选的.在您的特定示例中,我们可以使用装箱的特征对象返回您的咖喱函数.

The good news is this doesn't stop you from accomplishing what you want to accomplish because impl Trait is just syntax sugar and its use is optional. In your particular example we can use a boxed trait object to return your curried function.

fn add(x: i32) -> impl Fn(i32) -> Box<dyn Fn(i32) -> i32> {
    move |y: i32| {
        Box::new(move |z: i32| {
            x + y + z
        })
    }
}

fn main() {
    let add5 = add(5);
    let add5_10 = add5(10);
    println!("Call closure: {}", add5_10(6)); // prints "Call closure: 21"
}

操场

另请参阅:

这篇关于如何在Rust中实现多层次的curring函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆