Programing

Rust에서 함수를 작성하는 방법은 무엇입니까?

lottogame 2020. 11. 21. 08:20
반응형

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제약 조건 및 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 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

반응형