Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trait implementation with where clauses: Implementing a simple where clause

Tags:

types

rust

traits

I have been trying to learn Rust through rust-koans but ran into a wall with the following trait koan:

// There is an alternate syntax for placing trait bounds on a function, the
// where clause. Let's revisit a previous example, this time using 'where'.
#[test]
fn where_clause() {
    let num_one: u16 = 3;
    let num_two: u16 = 4;

    trait IsEvenOrOdd {
        fn is_even(&self) -> bool;
    }

    impl IsEvenOrOdd for u16 {
        fn is_even(&self) -> bool {
            self % 2 == 0
        }
    }

    fn asserts<T>(x: T, y: T) {
        assert!(!x.is_even());
        assert!(y.is_even());
    }

    asserts(num_one, num_two);
}

It seems the goal is to complete this code by creating a generic version of the IsEvenOrOdd implementation. In this case the generic type should have two bounds, the remainder operator and the PartialEq operator. Because the remainder right side and equivalence right side are integers, I eventually wrote the following spaghetti code:

use std::ops::Rem;

impl<T> IsEvenOrOdd for T
where
    T: Rem<u16> + Rem,
    <T as Rem<u16>>::Output: PartialEq<u16>,
{
    fn is_even(&self) -> bool {
        self % 2 == 0
    }
}

Still - the code doesn't compile. It seems that since T is dereferenced I would need to add bounds to the dereferenced value, but I cannot find any example of how to do that.

error[E0369]: binary operation `%` cannot be applied to type `&T`
   --> src\koans/traits.rs:142:13
    |
142 |             self % 2 == 0
    |             ^^^^^^^^
    |
    = note: an implementation of `std::ops::Rem` might be missing for `&T`

In short: What would be the idiomatic Rust way to solve this koan?

like image 843
devaj Avatar asked Nov 24 '25 08:11

devaj


1 Answers

I think you may have misinterpreted the intention of this exercise. What you want is this:

fn main() {
    let num_one: u16 = 3;
    let num_two: u16 = 4;

    trait IsEvenOrOdd {
        fn is_even(&self) -> bool;
    }

    impl IsEvenOrOdd for u16 {
        fn is_even(&self) -> bool {
            self % 2 == 0
        }
    }

    fn asserts<T>(x: T, y: T)
        where T: IsEvenOrOdd {
        assert!(!x.is_even());
        assert!(y.is_even());
    }

    asserts(num_one, num_two);
}

How did I come to this conclusion? Trying to compile and run the original code you posted results in the following error:

error[E0599]: no method named `is_even` found for type `T` in the current scope
  --> src/main.rs:16:20
   |
16 |         assert!(!x.is_even());
   |                    ^^^^^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `is_even`, perhaps you need to implement it:
       candidate #1: `main::IsEvenOrOdd`

This error tells us that to call the is_even method, you must implement IsEvenOrOdd. The comments on the top of the example you posted say to use the where clause on a function. Adding the where clause to the function asserts solves your problem and completes the exercise.

like image 126
Steampunkery Avatar answered Nov 28 '25 17:11

Steampunkery



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!