问题描述
我认为这两种方法是等效的,但是有一个错误。是什么原因?有没有更好的表达方式?
pub fn create_pair() -> () {
let vec_num = vec![1,2,3];
let vec_num2 = &vec_num;
let all = &vec_num
.iter()
.flat_map(move |a| vec_num2.iter().map(move |b| [a,b]))
.collect::<Vec<_>>();
println!("{:?}",all);
}
[[1,1],[1,2],3],[2,[3,3]]
pub fn create_pair() -> () {
let vec_num = vec![1,3];
let all = &vec_num
.iter()
.flat_map(move |a| &vec_num.iter().map(move |b| [a,all);
}
error[E0277]: `&std::iter::Map<std::slice::Iter<'_,{integer}>,[closure@src/main.rs:5:48: 5:63 a:_]>` is not an iterator
--> src/main.rs:5:10
|
5 | .flat_map(move |a| &vec_num.iter().map(move |b| [a,b]))
| ^^^^^^^^ `&std::iter::Map<std::slice::Iter<'_,[closure@src/main.rs:5:48: 5:63 a:_]>` is not an iterator
|
= help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Map<std::slice::Iter<'_,[closure@src/main.rs:5:48: 5:63 a:_]>`
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::iter::Map<std::slice::Iter<'_,[closure@src/main.rs:5:48: 5:63 a:_]>`
error[E0599]: no method named `collect` found for struct `std::iter::FlatMap<std::slice::Iter<'_,&std::iter::Map<std::slice::Iter<'_,[closure@src/main.rs:5:48: 5:63 a:_]>,[closure@src/main.rs:5:19: 5:64 vec_num:_]>` in the current scope
--> src/main.rs:6:10
|
6 | .collect::<Vec<_>>();
| ^^^^^^^ method not found in `std::iter::FlatMap<std::slice::Iter<'_,[closure@src/main.rs:5:19: 5:64 vec_num:_]>`
|
= note: the method `collect` exists but the following trait bounds were not satisfied:
`&std::iter::Map<std::slice::Iter<'_,[closure@src/main.rs:5:48: 5:63 a:_]>: std::iter::IntoIterator`
which is required by `std::iter::FlatMap<std::slice::Iter<'_,[closure@src/main.rs:5:19: 5:64 vec_num:_]>: std::iter::Iterator`
`std::iter::FlatMap<std::slice::Iter<'_,[closure@src/main.rs:5:19: 5:64 vec_num:_]>: std::iter::Iterator`
which is required by `&mut std::iter::FlatMap<std::slice::Iter<'_,[closure@src/main.rs:5:19: 5:64 vec_num:_]>: std::iter::Iterator`
解决方法
根据Rust reference,&
运算符的优先级比方法调用的优先级低。因此关闭:
move |a| &vec_num.iter().map(move |b| [a,b])
将首先尝试计算vec_num.iter().map(move |b| [a,b])
,然后引用该结果并将其返回。那根本不等于您的第一个样本。
我有一种直觉,你的意思是:
move |a| (&vec_num).iter().map(move |b| [a,b])
那也不起作用,但是出于完全不同的原因:
error: captured variable cannot escape `FnMut` closure body
--> src/main.rs:17:28
|
14 | let vec_num = vec![1,2,3];
| ------- variable defined here
...
17 | .flat_map(move |a| (&vec_num).iter().map(move |b| [a,b]))
| - ^^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | | |
| | | variable captured here
| | returns a reference to a captured variable which escapes the closure body
| inferred to be a `FnMut` closure
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore,they cannot allow references to captured variables to escape
error[E0505]: cannot move out of `vec_num` because it is borrowed
--> src/main.rs:17:19
|
15 | let all = &vec_num
| ------- borrow of `vec_num` occurs here
16 | .iter()
17 | .flat_map(move |a| (&vec_num).iter().map(move |b| [a,b]))
| -------- ^^^^^^^^ ------- move occurs due to use in closure
| | |
| | move out of `vec_num` occurs here
| borrow later used by call
error: aborting due to 2 previous errors
在将其移入闭包的同时,不能同时借用vec_num
进行方法调用。而且,由于闭包现在拥有vec_num
,因此您无法返回最终包含对vec_num
的引用的值,因为一旦您从闭包中返回,它将被删除。
如果您拿走move
,那么闭包将借用vec_num
而不是消耗它。
再次,根据Rust参考:
关闭可以捕获变量:
- 通过引用:&T
- 可变参考:&mut T
- 按值:T
它们优先通过引用捕获变量,并且仅在以下情况下变小
您不需要&
来指示应该通过引用捕获变量。这有效:
pub fn main() -> () {
let vec_num = vec![1,3];
let all = &vec_num
.iter()
.flat_map(|a| vec_num.iter().map(move |b| [a,b]))
.collect::<Vec<_>>();
println!("{:?}",all);
}