Generics 收集到Vec vs&Vec

Generics 收集到Vec vs&Vec,generics,vector,rust,vec,Generics,Vector,Rust,Vec,我有以下代码片段,不要质疑它们的意义 一,。递归获取向量的第n个元素 在第一个示例中,尾部变量为Vec类型,在第二个示例中,尾部变量为&Vec类型 问题: 为什么?为什么返回两种不同类型的代码的精确行? 在第二个示例中,如何返回Vec? 问题是: 示例1:使用 return helper(n, current_n + 1, &tail, head); // &tail 示例2:使用以下命令调用递归函数: return helper(tail, accumulator + 1)

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

一,。递归获取向量的第n个元素

在第一个示例中,尾部变量为Vec类型,在第二个示例中,尾部变量为&Vec类型

问题:

为什么?为什么返回两种不同类型的代码的精确行? 在第二个示例中,如何返回Vec? 问题是:

示例1:使用

return helper(n, current_n + 1, &tail, head); // &tail
示例2:使用以下命令调用递归函数:

return  helper(tail, accumulator + 1) // tail
将尾部更改为尾部(&T),一切正常。 目前我无法确切解释原因,所以我会等待接受这一正确答案,并希望其他人能够完全回答

在第二个示例中,Self::Item是T。因此,编译器试图通过查看tail的使用方式来猜测tail的类型。当您调用helper tail,…,编译器猜测tail应该具有与helper的第一个参数相同的类型,对于一些未知的类型U,aka&Vec。但是,&Vec没有实现FromIterator,因此编译器在这一点上退出

当您调用helper&tail,…,编译器猜测&tail对于某些U应该具有类型&Vec,因此tail应该具有类型Vec。然后,编译器可以继续并确定U==T,这将给出完整类型的tail作为Vec

顺便说一句,这里是您的第一个助手的一个更惯用的实现,它可以避免不必要的副本。对于第二个,可以做类似的事情:

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));
}

旁注:我知道你这样做只是为了练习,但要注意的是,对于未来的读者来说,将切片作为参数而不是对向量的不变引用更为惯用。给你的印象是,这两个变量有不同的类型?第二个示例根本不编译,可以通过在对helper的调用中将tail更改为&tail来修复。@justinas lol。。。你是对的,当我修改helper调用以返回helper&tail时,IntelliJ中的累加器+1,tail的“类型”将更改为Vec。但我还是不明白,为什么后面的线让尾巴。。。对那条线有影响让尾巴…@SvenMarnach IntelliJ说。它以某种方式解析了类型。@SleepyX667你能用一个最小的例子创建一个向量吗?这样每个人都在同一页上,观察到你做的相同的事情。一切正常,我等不及了。你可以尝试一个类似10000元素的向量。这是一个更地道的说法implementation@Stargateur:我得到:error[E0658]:子片模式不稳定,如果我不使用nighly channel。@SleepyX667所以使用,我使用的功能在rustc 1.42中得到稳定。这并没有多大变化,我的代码的重点是减少无用变量的使用。
return helper(n, current_n + 1, &tail, head); // &tail
return  helper(tail, accumulator + 1) // tail
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));
}