Youness Kafia
Youness Kafia

Reputation: 183

how to use Generics in functions and pattern matching in rust?

I'm solving a little math problem called the Syracuse problem (3n+1 problem).

Thing is i want my function to work for 2 types, one is u64 the other is a struct that extends the size of u64 by containing 2 u64 that i called U128.

my u64 function looks like this

fn syracuse(n: u64) -> u64 {
    match n % 2 {
        0 => n / 2,
        1 => 3 * n + 1,
        _ => 1,
    }
}

I've tried implementing a trait to my U128 and u64.

fn syracuse<T>(n: T) -> T where T : Add +Mul+Div+Rem + Basic0123 {
    match n % Basic0123::two() {
        Basic0123::zero() => n / Basic0123::two(),
        Basic0123::one() => Basic0123::three() * n + Basic0123::one(),
        _ => Basic0123::one(),
    }
}

It doesn't compile, the pattern matching doesn't like this. I'm new to rust and i'm trying to understand if creating a function with generic typing is okay for this problem that only treats 2 different types the DRY way or i should just stick with simply rewriting the function for the U128 type?

Upvotes: 0

Views: 572

Answers (1)

S&#233;bastien Renauld
S&#233;bastien Renauld

Reputation: 19672

I'm just going to assume most of the stuff in the comments has been dealt with and you're back to using the std::u128 primitive type rather than your own.

The proper way to implement the Syracuse conjecture on a generic type is as follows:

fn syracuse<T>(n: T) -> T
    where T : Copy + Eq + Add<Output = T> + Mul<Output = T> + Div<Output = T> + Rem<Output = T> + From<u32> {

    let zero:T = 0.into();
    match n % 2.into() == zero {
        true => n/(2.into()),
        false => n * (3.into()) + 1.into()
    }
}

In order of appearance:

  • Copy is required because we did not require Rem on &T, but on T
  • All the Output type specifications are so we do not implicitly change type - an operation on T will always map to T
  • We are requiring Eq so we can compare the result of the remainder
  • We are requiring From<u32> so we can into() every single numerical constant

A working version can be found here

Upvotes: 2

Related Questions