Rust에서 함수를 작성하는 방법은 무엇입니까?
두 가지 기능을 구성하는 함수를 작성하려고합니다. 초기 디자인은 매우 간단합니다. 두 개의 함수를 취하고 구성된 함수를 반환하는 함수는 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 포인트 아웃 , 수 있도록 당신 만 다시 구성 기능을 참조해야 할 일 :
let finally = compose(&*add_and_multiply, &*divide_and_subtract);
(Rust에서는 규칙에 따라 변수 이름이 snake_case에 있어야 함)
그러나 우리는 이것을 더 좋게 만들 수 있습니다!
Rust 1.26 이후로 추상 반환 유형을 사용할 수 있습니다 (이전에는으로 게이트가 지정됨 #![feature(conservative_impl_trait)]
). 이렇게하면 수명, 참조, Sized
제약 조건 및 Box
es 를 건너 뛸 수 있으므로 예제를 크게 단순화 할 수 있습니다 .
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 add_and_multiply = compose(|x| x * 2, |x| x + 2);
let divide_and_subtract = compose(|x| x / 2, |x| x - 2);
let finally = compose(add_and_multiply, 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));
}
참조를 추가 finally
하면 작동합니다.
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));
}
그렇지 않은 특성 객체를 역 참조 addAndMultiply
하거나 divideAndSubtract
발견합니다 Sized
. 제약 조건이 Box
있는 함수에 전달 되려면 로 래핑 되거나 참조되어야 Sized
합니다.
참고URL : https://stackoverflow.com/questions/45786955/how-to-compose-functions-in-rust
'Programing' 카테고리의 다른 글
MongoDB 및 Mongoose에서 전체 텍스트 검색을 수행하는 가장 좋은 방법 (0) | 2020.11.21 |
---|---|
비트 프로그래밍에서 (숫자 및-숫자)는 무엇을 의미합니까? (0) | 2020.11.21 |
C #에서 트리를 순회하는 재귀 람다 식 (0) | 2020.11.21 |
AppStore가없는 iPhone 앱 (0) | 2020.11.21 |
자바 스크립트의 배열 리터럴 표기법은 무엇이며 언제 사용해야합니까? (0) | 2020.11.21 |