Как реализовать черту для вектора универсального типа Vec <T>? - PullRequest
0 голосов
/ 17 мая 2018

Как реализовать черту ниже для вектора универсального типа Vec<T>?

Например, как реализовать черту ниже (работающую) Difference универсальным способом (например, чтобы она быладействительно для Vec<i32>, Vec<f32>, Vec<f64>)?

trait Difference {
    fn diff(&self) -> Vec<f64>;
}

impl Difference for Vec<f64> {
    fn diff(&self) -> Vec<f64> {
        self.windows(2)
            .map(|slice| (slice[0] - slice[1]))
            .collect()
    }
}

fn main() {
    let vector = vec![1.025_f64, 1.028, 1.03, 1.05, 1.051];
    println!("{:?}", vector.diff());
}

Если посмотреть на документацию , кажется, что это должно быть что-то вроде:

trait Difference<Vec<T>> {
    fn diff(&self) -> Vec<T>;
}

impl Difference for Vec<T> {
    fn diff(&self) -> Vec<T> {
        self.windows(2)
            .map(|slice| (slice[0] - slice[1]))
            .collect()
    }
}

fn main() {
    let vector = vec![1.025_f64, 1.028, 1.03, 1.05, 1.051];
    println!("{:?}", vector.diff());
}

Однако приведенные выше результаты приводят к:

error: expected one of `,`, `:`, `=`, or `>`, found `<`
 --> src/main.rs:2:21
  |
2 | trait Difference<Vec<T>> {
  |                     ^ expected one of `,`, `:`, `=`, or `>` here

Я пробовал несколько других вариантов, однако все они приводили к гораздо более длинным сообщениям об ошибках.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Вам необходимо параметризовать более T, а не Vec<T>.Тогда вам также нужно ограничить T, чтобы вы могли выполнять вычитание (с чертой Sub) и чтобы значения можно было скопировать в память (с чертой Copy).Числовые типы будут в основном реализовывать эти черты.

use std::ops::Sub;

trait Difference<T> {
    fn diff(&self) -> Vec<T>;
}

impl<T> Difference<T> for Vec<T>
where
    T: Sub<Output = T> + Copy,
{
    fn diff(&self) -> Vec<T> {
        self.windows(2).map(|slice| slice[0] - slice[1]).collect()
    }
}

fn main() {
    let vector = vec![1.025_f64, 1.028, 1.03, 1.05, 1.051];
    println!("{:?}", vector.diff());
}
0 голосов
/ 17 мая 2018

Правильный синтаксис:

trait Difference<T> { /* ... */ }

impl<T> Difference<T> for Vec<T> { /* ... */ }

Тогда вам потребуется, чтобы T реализовал вычитание:

error[E0369]: binary operation `-` cannot be applied to type `T`
 --> src/main.rs:9:26
  |
9 |             .map(|slice| (slice[0] - slice[1]))
  |                          ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `T` might need a bound for `std::ops::Sub`

И вы можете скопировать значения:

error[E0508]: cannot move out of type `[T]`, a non-copy slice
  --> src/main.rs:10:27
   |
10 |             .map(|slice| (slice[0] - slice[1]))
   |                           ^^^^^^^^ cannot move out of here
impl<T> Difference<T> for Vec<T>
where
    T: std::ops::Sub<Output = T> + Copy,
{
    // ...
}

Или что ссылки на T могут быть вычтены:

impl<T> Difference<T> for Vec<T>
where
    for<'a> &'a T: std::ops::Sub<Output = T>,
{
    fn diff(&self) -> Vec<T> {
        self.windows(2)
            .map(|slice| &slice[0] - &slice[1])
            .collect()
    }
}

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...