Что такое сигнатура типа idiomati c для функции, которая принимает тип generi c, который должен быть ссылкой? - PullRequest
0 голосов
/ 18 марта 2020
#[allow(dead_code)]
fn contains<'a, V, T, Q>(arr: V, value: &Q) -> bool
where
    T: 'a + std::cmp::PartialEq<Q>,
    V: std::iter::IntoIterator<Item = &'a T>,
{
    arr.into_iter().any(|v| v == value)
}

#[test]
fn test_contains_hash_set() {
    use std::collections::HashSet;

    let hs_str: HashSet<&str> = ["a", "b", "c"].iter().copied().collect();
    let hs_string: HashSet<String> = vec!["a".to_string(), "b".to_string(), "c".to_string()]
        .into_iter()
        .collect();

    let value_str = "b";
    let value_string = String::from(value_str);

    assert!(contains(&hs_str, &value_string));
    assert!(contains(&hs_string, &value_str));
    assert!(contains(&hs_string, &"a"));
}

#[test]
fn test_contains_vec() {
    let array_str = ["a", "b", "c"];
    let array_string = ["a".to_string(), "b".to_string(), "c".to_string()];

    let value_str = "b";
    let value_string = String::from(value_str);

    assert!(contains(&array_str, &value_string));
    assert!(contains(&array_string, &value_str));
    assert!(contains(&array_string, &"b"));

    //assert!(contains(array_string, &"b"));
    // ^^^ testing the compiler error for when there is no &
}

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

Игнорируя оператор where, я мог прочитать сигнатуру типа contains как contains(V, &Q) -> bool. Я бы предположил, что для любого V это конкретный тип, который будет перемещен.

Включая оператор where, V становится ссылкой на что-то, что может быть превращено в итератор &T s. Исходя из моего предыдущего предположения, я бы хотел превратить V в &V; однако он не будет компилироваться, поскольку становится ссылкой на ссылку на что-либо.

Если другой разработчик не знал, как реализован std::iter::IntoIterator<Item = &'a T>, они бы предположили, что V - это конкретный тип, который перемещается? Есть ли способ показать в сигнатуре типа, что V ожидает ссылку?

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

V не ожидает ссылку. V случается с быть ссылкой во всех местах, где вы его использовали, но это не обязательно.

Поскольку функция contains подписи типа стоит, может ли это быть написано более идиоматически c способом?

...