0

我有以下代码片段(不要质疑它们的意义;))

1.递归获取Vec的第n个元素

fn helper<T: Clone>(n: usize, current_n: usize, current_xs: &Vec<T>, accumulator: Option<T>) -> Option<T> {
    if current_n > n {
        accumulator
    } else {
        let head = current_xs.get(0).cloned();
        let tail = current_xs.clone().into_iter().skip(1).collect();
        return helper(n, current_n + 1, &tail, head);
    }
}

2. 递归获取 Vec 的长度

fn helper<T: Clone>(current_xs: &Vec<T>, accumulator: usize) -> usize {
    if current_xs.is_empty() {
        accumulator
    } else {
        let tail = current_xs.clone().into_iter().skip(1).collect();
        return  helper(tail, accumulator + 1)
    }
}

我的问题是关于那条线:

let tail = current_xs.clone().into_iter().skip(1).collect();

在第一个示例中,tail变量是 Type Vec<T>,在第二个示例中,tail变量是 type &Vec<?>

问题:

  • 为什么?为什么返回两种不同类型的确切代码行?
  • 如何Vec<T>在第二个示例中返回 a ?

锈游乐场

4

2 回答 2

2

在您的第二个示例中,collect可以返回任何实现FromIterator<Self::Item>(这里Self::ItemT)。所以编译器试图tail通过查看它的使用方式来猜测它的类型。当您调用helper (tail, …)时,编译器猜测tail应该与第一个参数具有相同的类型helper,也就是&Vec<U>一些未知类型U。但是,&Vec<U>没有实现,因此FromIterator<T>编译器此时退出。

OTOH 当您调用时helper (&tail, …),编译器猜测&tail应该有&Vec<U>一些类型U,因此tail应该有类型Vec<U>。然后编译器可以继续并确定U==T,这给出了tailas的完整类型Vec<T>


顺便说一句,这是您的第一个更惯用的实现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 = &current_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));
}

操场

于 2020-01-21T09:27:40.233 回答
-1

问题是:

示例 1:调用递归函数

return helper(n, current_n + 1, &tail, head); // &tail

示例 2:调用递归函数:

return  helper(tail, accumulator + 1) // tail

更改tail&tail一切正常。目前我无法准确解释原因,所以我会等待接受这个作为正确答案,并希望其他人可以完全回答。

锈游乐场

于 2020-01-21T08:38:34.437 回答