Эта функция возвращает первый элемент коллекции, подобной списку.Он работает для различных типов списков:
fn first<T: Copy>(x: impl Deref<Target=[T]>) -> T {
x[0]
}
Например, он компилируется и запускается:
let data: Vec<usize> = vec![3, 4];
assert_eq!(first(data), 3);
let data: &[usize] = &[3, 4];
assert_eq!(first(data), 3);
let data: Rc<[usize]> = Rc::new([3, 4]);
assert_eq!(first(data), 3);
Также компилируется и запускается:
fn stub(x: &[usize]) -> usize {
first(x)
}
let data: &[usize; 2] = &[3, 4];
assert_eq!(stub(data), 3);
assert_eq!(stub(&[3, 4]), 3);
Но это не скомпилируется:
let data: &[usize; 2] = &[3, 4];
assert_eq!(first(data), 3); // Fails.
assert_eq!(first(&[3, 4]), 3); // Fails.
Сообщение об ошибке:
type mismatch resolving `<&[usize; 2] as std::ops::Deref>::Target == [_]`
Мне кажется, я понимаю, что происходит.Для каждого типа T
существует уникальный тип <T as Deref>::Target
.Когда T
равен &[usize; 2]
, целью является [usize; 2]
, а не [usize]
.Компилятор может привести &[T; 2]
к &[T]
, если я его явно попросил, например, с помощью let
или stub()
, но если я этого не сделаю, он не сможет понять, что принудительное действие требуется.
Но это расстраивает.Для человека совершенно очевидно, для чего предназначены ошибочные вызовы, и компилятор понимает, что требуется для Vec<usize>
, Box<[usize]>
, Rc<[usize]>
, &[usize]
и т. Д., Поэтому не кажется бесполезным пытатьсячтобы он работал и для [usize; 2]
.
Вопрос: Есть ли удобный способ написать first()
, чтобы последние два вызова тоже работали?Если нет, то есть ли синтаксис, чтобы попросить компилятор принудительно установить &[usize; 2]
в &[usize]
, , то есть без использования let
или stub()
?
Детская площадка .