rus*_*yhu 8 closures functional-programming function currying rust
我尝试在 Rust 中实现类似于函数式编程术语的柯里化函数:
fn add_origin(x: i32) -> impl Fn(i32) -> i32 {
return move |y| {
x + y
};
}
fn main() {
let add5 = add_origin(5);
println!("Call closure: {}", add5(6));
}
Run Code Online (Sandbox Code Playgroud)
这是可行的,但如果我再更深一层:
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));
}
Run Code Online (Sandbox Code Playgroud)
编译器不接受并告诉我:
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
Run Code Online (Sandbox Code Playgroud)
为什么这是不允许的?Rust 有更好的选择吗?
impl Trait语法只能用在函数签名的参数位置或返回位置。这两个都很好:
fn takes_fn(fn_arg: impl Fn(i32) -> i32) {}
fn returns_fn() -> impl Fn(i32) -> i32 {
|x| x
}
Run Code Online (Sandbox Code Playgroud)
然而,这些都不起作用:
fn takes_fn(fn_arg: impl Fn(i32) -> impl Fn(i32) -> i32) {}
fn returns_fn() -> impl Fn(i32) -> impl Fn(i32) -> i32 {
|x| x
}
Run Code Online (Sandbox Code Playgroud)
因为第二个嵌套impl Trait不再位于参数或返回位置,但现在是参数或返回类型签名的一部分,这不是允许的地方。基本上,impl Trait无论您将它们放在哪里,多个嵌套都永远不会工作,并且您总是会得到相同的编译错误。
好消息是,这不会阻止您完成您想要完成的任务,因为impl Trait它只是语法糖,并且它的使用是可选的。在您的特定示例中,我们可以使用盒装特征对象来返回您的柯里化函数。
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"
}
Run Code Online (Sandbox Code Playgroud)
也可以看看: