В чем разница между `Some(&a) => a` и`Some(a) => *a` при сопоставлении с Option?
Почему это проходит:
fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
match v.get(0) {
Some(&a) => (v, a),
_ => (v, 0)
}
}
но это не так
fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
match v.get(0) {
Some(a) => (v, *a),
_ => (v, 0)
}
}
error[E0505]: cannot move out of `v` because it is borrowed
--> src/main.rs:7:21
|
6 | match v.get(0) {
| - borrow of `v` occurs here
7 | Some(a) => (v, *a),
| ^ move out of `v` occurs here
2 ответа
v.get(0)
возвращает ссылку на элемент в векторе, поэтому вы соответствуете &isize
, Vec
сейчас занято в матчевой руке.
В первом фрагменте кода вы копируете isize
, Итак Vec
не заимствовано здесь. Во втором фрагменте Vec
все еще заимствован, поэтому вы не можете вывести его из области видимости.
Тем не менее, вы должны рассмотреть возможность использования if let
или же unwrap_or
:
fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
let a = v.get(0).cloned();
(v, a.unwrap_or(0))
}
fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
if let Some(&a) = v.get(0) {
(v, a)
} else {
(v, 0)
}
}
Смотрите также:
В первом фрагменте, когда вы печатаете Some(&a)
Вы не занимаетесь v
так как a
копируется.
Во втором случае Some(a)
имеет тип Option<&isize>
поэтому он содержит ссылку на v
, Когда вы пытаетесь переместить его, он вызывает ошибку. Если вы сначала скопируете его, а затем вернете пару, это сработает ( однако вам нужна функция NLL):
#![feature(nll)]
fn main() {
println!("{:?}", f(vec![1]))
}
fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
match v.get(0) {
Some(a) => {
let a = *a; // v is no more borrowed
(v, a)
},
_ => (v, 0)
}
}
Средство проверки заимствований не может быть идеальным, поэтому вы часто сталкиваетесь с некоторыми противоречивыми вещами.