gpt4 book ai didi

functional-programming - 如何在 Rust 中组合函数?

转载 作者:行者123 更新时间:2023-11-29 07:40:04 26 4
gpt4 key购买 nike

我正在尝试编写一个由两个函数组成的函数。初始设计非常简单:一个函数接受两个函数并返回一个组合函数,然后我可以将其与其他函数组合,因为 Rust 没有剩余参数。我遇到了一堵由令人沮丧的无用编译器错误构成的墙。

我的撰写功能:

fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a>
where
F: 'a + Fn(A) -> B + Sized,
G: 'a + Fn(B) -> C + Sized,
{
Box::new(move |x| g(f(x)))
}

我想如何使用它:

fn main() {
let addAndMultiply = compose(|x| x * 2, |x| x + 2);
let divideAndSubtract = compose(|x| x / 2, |x| x - 2);

let finally = compose(*addAndMultiply, *divideAndSubtract);
println!("Result is {}", finally(10));
}

编译器不喜欢那样,无论我尝试什么,特征边界都不会满足。错误是:

error[E0277]: the size for values of type `dyn std::ops::Fn(_) -> _` cannot be known at compilation time
--> src/main.rs:13:19
|
13 | let finally = compose(*addAndMultiply, *divideAndSubtract);
| ^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn std::ops::Fn(_) -> _`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
note: required by `compose`
--> src/main.rs:1:1
|
1 | / fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a>
2 | | where
3 | | F: 'a + Fn(A) -> B + Sized,
4 | | G: 'a + Fn(B) -> C + Sized,
5 | | {
6 | | Box::new(move |x| g(f(x)))
7 | | }
| |_^

最佳答案

作为@ljedrz points out ,要让它工作,你只需要再次引用组合函数:

let finally = compose(&*multiply_and_add, &*divide_and_subtract);

(请注意,在 Rust 中,约定规定变量名应采用 snake_case)


但是,我们可以做得更好!

从 Rust 1.26 开始,我们可以使用 abstract return types (以前以 #![feature(conservative_impl_trait)] 为特色)。这可以帮助您大大简化示例,因为它允许您跳过生命周期、引用、Sized 约束和 Boxes:

fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(A) -> B,
G: Fn(B) -> C,
{
move |x| g(f(x))
}

fn main() {
let multiply_and_add = compose(|x| x * 2, |x| x + 2);
let divide_and_subtract = compose(|x| x / 2, |x| x - 2);

let finally = compose(multiply_and_add, divide_and_subtract);
println!("Result is {}", finally(10));
}

最后,既然你提到了剩余参数,我怀疑你真正想要的是有一种方法可以灵活地链式组合任意数量的函数。我为此编写了这个宏:

macro_rules! compose {
( $last:expr ) => { $last };
( $head:expr, $($tail:expr), +) => {
compose_two($head, compose!($($tail),+))
};
}

fn compose_two<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(A) -> B,
G: Fn(B) -> C,
{
move |x| g(f(x))
}

fn main() {
let add = |x| x + 2;
let multiply = |x| x * 2;
let divide = |x| x / 2;
let intermediate = compose!(add, multiply, divide);

let subtract = |x| x - 2;
let finally = compose!(intermediate, subtract);

println!("Result is {}", finally(10));
}

关于functional-programming - 如何在 Rust 中组合函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45786955/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com