收集到 Vec vs &Vec
Collecting to a Vec vs &Vec
我有以下代码片段(不要质疑它们的意义;))
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
变量的类型为 Vec<T>
,在第二个示例中,tail
变量的类型为 &Vec<?>
.
问题:
- 为什么?为什么 return 是两种不同类型的确切代码行?
- 如何在第二个例子中return一个
Vec<T>
?
问题是:
例1:调用递归函数
return helper(n, current_n + 1, &tail, head); // &tail
示例 2: 调用递归函数:
return helper(tail, accumulator + 1) // tail
将 tail
更改为 &tail
一切正常。
目前我无法准确解释原因,所以我会等待接受这个作为正确答案,并希望其他人能够完全回答它。
在您的第二个示例中,collect
can return anything that implements FromIterator<Self::Item>
(这里 Self::Item
是 T
)。所以编译器试图通过查看它的使用方式来猜测 tail
的类型。当您调用 helper (tail, …)
时,编译器猜测 tail
应该与 helper
的第一个参数具有相同的类型,也就是 &Vec<U>
对于一些未知类型 U
.但是,&Vec<U>
没有 实现 FromIterator<T>
,因此编译器此时退出。
OTOH 当你调用 helper (&tail, …)
时,编译器猜测 &tail
对于某些 U
应该有类型 &Vec<U>
,因此 tail
应该有类型Vec<U>
。然后编译器可以继续并确定 U==T
,它给出 tail
的完整类型为 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 = ¤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));
}
我有以下代码片段(不要质疑它们的意义;))
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
变量的类型为 Vec<T>
,在第二个示例中,tail
变量的类型为 &Vec<?>
.
问题:
- 为什么?为什么 return 是两种不同类型的确切代码行?
- 如何在第二个例子中return一个
Vec<T>
?
问题是:
例1:调用递归函数
return helper(n, current_n + 1, &tail, head); // &tail
示例 2: 调用递归函数:
return helper(tail, accumulator + 1) // tail
将 tail
更改为 &tail
一切正常。
目前我无法准确解释原因,所以我会等待接受这个作为正确答案,并希望其他人能够完全回答它。
在您的第二个示例中,collect
can return anything that implements FromIterator<Self::Item>
(这里 Self::Item
是 T
)。所以编译器试图通过查看它的使用方式来猜测 tail
的类型。当您调用 helper (tail, …)
时,编译器猜测 tail
应该与 helper
的第一个参数具有相同的类型,也就是 &Vec<U>
对于一些未知类型 U
.但是,&Vec<U>
没有 实现 FromIterator<T>
,因此编译器此时退出。
OTOH 当你调用 helper (&tail, …)
时,编译器猜测 &tail
对于某些 U
应该有类型 &Vec<U>
,因此 tail
应该有类型Vec<U>
。然后编译器可以继续并确定 U==T
,它给出 tail
的完整类型为 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 = ¤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));
}