#[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 способом?