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`.
Further Notes
- I am aware that
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.) - I also tried collecting it into a container first.
(0..len).collect::<Vec<_>>().iter().cloned().map(...)
- I tried the suggested
move
but thennumbers
is also moved and hence not available in the next loop. - There is no threading or async happening anywhere in this code example.
- Shepmaster says in this answer that I cannot make lifetime annotations on closures.
- The reason I don't write two raw loops with early return is, that if I want to say, run
.any()
to find if a specific value is present, I'd have to move the two loops into a separate function as I cannot putreturn true;
inside the loop unless it's in a separate function.