#rust #reference
#Ржавчина #ссылка #итератор #владение
Вопрос:
Я столкнулся с ошибкой при попытке использовать функцию get_even_numbers()
для заимствования vec v
, передавая ее по ссылке amp;v
, а не по значению v
.
fn get_even_numbers(v: amp;Vec<i32>) -> Vec<i32> {
v.iter().filter(|x| x % 2 == 0).collect()
}
fn main() {
let v: Vec<i32> = (0..10).collect();
let even: Vec<i32> = get_even_numbers(amp;v);
println!("Even numbers: {:?}", even);
}
error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `amp;i32`
--> src/main.rs:2:37
|
2 | v.iter().filter(|x| x % 2 == 0).collect()
| ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=amp;i32>`
|
= help: the trait `FromIterator<amp;i32>` is not implemented for `Vec<i32>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
note: required by a bound in `collect`
Почему приведенное выше выдает ошибку, но передача ее по значению не дает, как показано ниже?
fn get_even_numbers(v: Vec<i32>) -> Vec<i32> {
v.into_iter().filter(|x| x % 2 == 0).collect()
}
fn main() {
let v: Vec<i32> = (0..10).collect();
let even: Vec<i32> = get_even_numbers(v);
println!("Even numbers: {:?}", even);
}
Even numbers: [0, 2, 4, 6, 8]
Я использовал .iter()
внутри функции при передаче по ссылке и .into_iter()
при передаче по значению, не уверен, что это правильные функции для использования.
Комментарии:
1. Перебор заимствованного вектора перебирает ссылки на значения. Для передачи фактических значений потребуется переместить их из вектора, а это разрешено только в том случае, если сам вектор используется в процессе. Именно поэтому версия с
into_iter()
works — посколькуinto_iter()
она использует вектор, она передает право собственности на элементы vector потребителю итератора. Посколькуi32
isCopy
, вы можете исправить заимствованную версию, добавив разыменование, например, изменив.collect()
на.copied().collect()
.
Ответ №1:
Используйте v.iter().filter(|x| x % 2 == 0).cloned().collect()
. Это (тривиально) клонирует каждую из amp;i32
ссылок в фактические i32
значения.
Комментарии:
1. Вы можете использовать
copied()
вместоcloned()
того, чтобы утверждать (во время компиляции), что клон тривиален.