Реализация черты с предложениями where: Реализация простого предложения where - PullRequest
0 голосов
/ 15 декабря 2018

Я пытался выучить Rust через rust-koans , но натолкнулся на стену со следующей чертой коана:

// 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);
}

Кажется, цель состоит в том, чтобы завершить этот кодсоздание общей версии реализации IsEvenOrOdd.В этом случае универсальный тип должен иметь две границы: оператор остатка и оператор PartialEq.Поскольку остальная правая часть и эквивалентная правая часть являются целыми числами, я в конечном итоге написал следующий код спагетти:

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
    }
}

Тем не менее - код не компилируется.Кажется, что, поскольку T разыменовано, мне нужно было бы добавить границы к разыменованному значению, но я не могу найти никакого примера того, как это сделать.

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`

Короче говоря: что будет идиоматическим Rustспособ решить этот коан?

1 Ответ

0 голосов
/ 20 декабря 2018

Я думаю, вы, возможно, неправильно истолковали намерение этого упражнения.Что вы хотите, это:

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);
}

Как я пришел к такому выводу?Попытка скомпилировать и запустить исходный код, который вы опубликовали, приводит к следующей ошибке:

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`

Эта ошибка говорит нам, что для вызова метода is_even необходимо реализовать IsEvenOrOdd.В комментариях в верхней части примера, который вы разместили, говорится, что для использования функции используется предложение where.Добавление предложения where к функции asserts решит вашу проблему и завершит упражнение.

...