How do I write a lazily evaluated double for loop in a functional style in Rust?
The borrowed value is of type usize, which should be trivially copyable.
fn main() {
let numbers: Vec<i32> = (1..100).collect();
let len = numbers.len();
let _sums_of_pairs: Vec<_> = (0..len)
.map(|j| ((j + 1)..len).map(|k| numbers[j] + numbers[k]))
.flatten()
.collect();
}
error[E0373]: closure may outlive the current function, but it borrows `j`, which is owned by the current function
--> src/bin/example.rs:6:37
|
6 | .map(|j| ((j + 1)..len).map(|k| numbers[j] + numbers[k]))
| ^^^ - `j` is borrowed here
| |
| may outlive borrowed value `j`
|
note: closure is returned here
--> src/bin/example.rs:6:18
|
6 | .map(|j| ((j + 1)..len).map(|k| numbers[j] + numbers[k]))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `j` (and any other referenced variables), use the `move` keyword
|
6 | .map(|j| ((j + 1)..len).map(move |k| numbers[j] + numbers[k]))
| ^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0373`.
Itertools::combinations(2)
does the job. However, I don't want to use it because (1) I want to know how to do it myself and (2) it might be the reason my code is slow, and I want to eliminate that source. (Update: Itertools::tuple_combinations<(_, _)>()
is much, much faster and lets one code this in a functional style.)(0..len).collect::<Vec<_>>().iter().cloned().map(...)
move
but then numbers
is also moved and hence not available in the next loop..any()
to find if a specific value is present, I'd have to move the two loops into a separate function as I cannot put return true;
inside the loop unless it's in a separate function.To work around the issue, you can borrow &numbers
up front and just shadow numbers
. Then after that you can add move
to the second closure.
fn main() {
let numbers: Vec<i32> = (1..100).collect();
let len = numbers.len();
let numbers = &numbers;
let _sums_of_pairs: Vec<_> = (0..len)
.map(|j| ((j + 1)..len).map(move |k| numbers[j] + numbers[k]))
.flatten()
.collect();
}