Во втором примере collect
может вернуть все, что реализует FromIterator<Self::Item>
(здесь Self::Item
равно T
). Поэтому компилятор пытается угадать тип tail
, посмотрев, как он используется. Когда вы вызываете helper (tail, …)
, компилятор предполагает, что tail
должен иметь тот же тип, что и первый аргумент helper
, то есть &Vec<U>
для некоторого пока еще неизвестного типа U
. Однако &Vec<U>
не не реализует FromIterator<T>
, поэтому на этом этапе компилятор выручает.
OTOH, когда вы вызываете helper (&tail, …)
, компилятор предполагает, что &tail
должен иметь введите &Vec<U>
для некоторых U
, и поэтому tail
должен иметь тип Vec<U>
. Затем компилятор может продолжить и определить, что U==T
, что дает полный тип tail
как Vec<T>
.
В качестве отступления, здесь приведена более идиоматическая c реализация вашего первый helper
, который избегает ненужных копий. Нечто подобное можно сделать и для второго:
fn helper<T: Clone> (n: usize, current_n: usize, current_xs: &[T], accumulator: Option<&T>) -> Option<T>
{
if current_n > n {
accumulator.cloned()
} else {
let head = current_xs.get (0);
let tail = ¤t_xs[1..];
return if tail.is_empty() {
None
} else {
helper (n, current_n + 1, tail, head)
};
}
}
fn main() {
let v = vec![1, 2, 3, 4, 5];
println!("Element 3: {:?}", helper (3, 0, &v, None));
println!("Element 10: {:?}", helper (10, 0, &v, None));
}
Детская площадка