How to pass a function to two arguments?

I have the following two functions:

fn plus<T: std::ops::Add>(a: T, b: T) -> <T as std::ops::Add>::Output { a + b }
fn minus<T: std::ops::Sub>(a: T, b: T) -> <T as std::ops::Sub>::Output { a - b }

// let a_plus_abs = |a, b| (if b >= 0 {plus} else {minus})(a, b);

And I want to express something similar to this:

function plus(a, b) { return a + b; }
function minus(a, b) { return a - b; }

function a_plus_abs_b(a, b) {
  return (b >= 0 ? plus : minus)(a, b);
}

How can I translate a_plus_abs_b(a, b) to Rust?

Here:

fn a_plus_abs_b<
    T: std::ops::Add + 
       std::ops::Sub<Output = <T as std::ops::Add>::Output> + 
       std::cmp::PartialOrd
>(a: T, b: T, zero: T) -> <T as std::ops::Add>::Output {
    if b >= zero {
        plus
    } else {
        minus
    }(a, b)
}

You could probably provide a zero trait or use a preexisting one, but passing in a zero parameter is the most straightforward way, especially if you like relying on only the standard library. Not exactly the most idiomatic thing if you're using it often though, so perhaps the trait solution would scale the best.

1 Like

If you want a Zero trait, then use the num crate

1 Like

I just used hard-coded zero:

#[test]
fn te4() {
    fn plus<T: std::ops::Add>(a: T, b: T) -> <T as std::ops::Add>::Output {
        a + b
    }
    fn minus<T: std::ops::Sub>(a: T, b: T) -> <T as std::ops::Sub>::Output {
        a - b
    }
    fn a_plus_abs<T>(a: T, b: T) -> <T as std::ops::Add>::Output
    where
        T: std::cmp::PartialOrd
            + std::convert::From<u8>
            + std::ops::Add
            + std::ops::Sub<Output = <T as std::ops::Add>::Output>,
    {
        (if b >= 0.into() { plus } else { minus })(a, b)
    }

    assert_eq!(a_plus_abs(5, -4), 9);
}