# How to get out of this "move" hell?

Whats the right "move" to make this work?

``````fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
let itera = nums.iter().copied().enumerate();
let iterb = itera.clone();
let iterc = iterb.clone();

itera.flat_map(|(i, u)| {
iterb.filter(move |(j, ..)| j != &i)
.flat_map(move |(j, v)| {
iterc.filter(move |&(k, w)| j != k && k != i && u + v + w == 0)
.map(|(.., w)| vec![u, v, w])
})
}).collect()
}
``````

First, it looks like you want a new version of the iterator at each level of the nesting, and not just a single clone for the second and third level at the top, right? So the first step would be creating a new iterator inside each `flat_map`. `iter_a` is consumed by then, so we can't clone it; let's just make the same iterator anew.

``````    itera
.flat_map(|(i, u)| {
let iterb = nums.iter().copied().enumerate();
iterb
.filter(move |(j, ..)| j != &i)
.flat_map(move |(j, v)| {
let iterc = nums.iter().copied().enumerate();
iterc
.filter(move |&(k, w)| j != k && k != i && u + v + w == 0)
.map(|(.., w)| vec![u, v, w])
})
})
.collect()
``````

But Rust still doesn't like this because you're `move`-ing `nums` everywhere now. You can dodge this one by only moving a reference to `nums` instead, because shared references implement `Copy`.

``````fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
let nums = &nums;
// ...
``````

Then I still get a

``````error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
``````

But everything we're working with at this point should be `Copy` (shared references or `i32`), so I just slap one more `move` on the guilty closure (the last closure in the function).

Here's the end result.

Incidentally, at this point it's clear that since you're only iterating things out and copying, you never really needed to consume the `Vec` (`nums`), and you could change the signature to

``````fn three_sum(nums: &[i32]) -> Vec<Vec<i32>> {
// And no more need for `let nums = &nums` as it's already a shared ref.
``````

Basically this is a messy exercise of working around `move` closures being everything-or-nothing. The workaround was making the "everything" case work by making everything `Copy`, since you didn't need anything more than a shared reference to `nums` anyway.

Edit: Alternatively, use `for` loops to avoid so many nested closures.

4 Likes

Thanks for the explanation

Here’s another solution

``````fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
let iter = &nums.iter().copied().enumerate();

iter.clone()
.flat_map(|(i, u)| {
iter.clone()
.filter(move |(j, ..)| j != &i)
.flat_map(move |(j, v)| {
iter.clone()
.filter(move |&(k, w)| j != k && k != i && u + v + w == 0)
.map(move |(.., w)| vec![u, v, w])
})
})
.collect()
}
``````
2 Likes