Какое объявление типа мне следует использовать для создания моего собственного метода HashMap? - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь разобраться в системе типов Rust.

use std::collections::HashSet;

fn hs_contains<T>(hs: &HashSet<T>, value: &T) -> bool
where 
    T: PartialEq,
{
    hs.iter().any(|v| v == value)
}

fn main() {
    // move strings into HashSet
    let known_values: HashSet<&str> = ["a", "b", "c"].iter().cloned().collect();

    // provided an Vec<String>
    let provided_values: Vec<String> = vec!["a".to_string(), "b".to_string(), "z".to_string()];

    // hash set of refrences
    let mut found: HashSet<&str> = HashSet::new();
    found.insert(&provided_values[0]);
    found.insert(&provided_values[1]);
    found.insert(&provided_values[2]);

    let missing: HashSet<_> = known_values.difference(&found).collect();

    let value: &String = &provided_values[1];

    hs_contains(&known_values, value);
    hs_contains(&missing, "c");

    println!("missing: {:#?}", missing);
}

( Playground )

Пример кода не компилируется, поскольку типы не приводятся , Можно ли придумать объявление типа для hs_contains, которое будет удовлетворять условиям внизу примера:

hs_contains(&known_values, value);
hs_contains(&missing, "c");

Почему бы мне просто не использовать HashSet::contains?

Замена hs_contains на HashSet::contains

known_values.contains(value);
missing.contains(&"c");

Результатом является следующая ошибка компиляции

error[E0277]: the trait bound `&str: std::borrow::Borrow<std::string::String>` is not satisfied
  --> src/main.rs:38:18
   |
38 |     known_values.contains(value);
   |                  ^^^^^^^^ the trait `std::borrow::Borrow<std::string::String>` is not implemented for `&str`

Единственный другой известный мне способ сделать эту работу -

known_values.iter().any(|v| v == value);

Это вызвало у меня интерес к тому, как определить функцию с объявлением типа, которое могло бы инкапсулировать вышесказанное.

1 Ответ

0 голосов
/ 16 марта 2020

Одно небольшое изменение может привести к компиляции: переместите & из объявления функции внутрь тела функции

fn hs_contains<T>(hs: &HashSet<T>, value: T) -> bool
where
    T: std::cmp::PartialEq,
{
    hs.iter().any(|v| v == &value)
}

и добавьте & к "c"

hs_contains(&missing, &"c" );

( Детская площадка )


Теперь, почему движение & внутри функции отличается?

Как объяснил Макс в комментариях ниже

Когда вы используете <T> и позже value:T, вы просите Руста выяснить, что на самом деле является T. В вашем случае это должна быть ссылка на str. Когда вы используете значение &T, вы теперь запрашиваете ссылку на ссылку str (a &&str)

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