Lifetime issue when matching iterator over matrix elements

My goal is to get an iterator over all the elements in the matrix along with the row number associated with each element.

The following is a simplified version of the lifetime problem in which I run.

fn main() { let mat = [ [1i32, 2, 3], [4, 5, 6], [7, 8, 9] ]; // Create an iterator that produces each element alongside its row number. let all_elems = mat.iter().enumerate().flat_map(|(row, arr)| { arr.iter().map(|elem| (row, elem)) // Error occurs here. }); for (row, elem) in all_elems { println!("Row: {}, Elem: {}", row, elem); } } 

Here is the error I get:

 <anon>:10:9: 10:43 error: cannot infer an appropriate lifetime for lifetime parameter 'r in function call due to conflicting requirements <anon>:10 arr.iter().map(|elem| (row, elem)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <anon>:10:24: 10:42 note: first, the lifetime cannot outlive the expression at 10:23... <anon>:10 arr.iter().map(|elem| (row, elem)) ^~~~~~~~~~~~~~~~~~ <anon>:10:24: 10:42 note: ...so type `|&i32| -> (uint, &i32)` of expression is valid during the expression <anon>:10 arr.iter().map(|elem| (row, elem)) ^~~~~~~~~~~~~~~~~~ <anon>:10:9: 10:43 note: but, the lifetime must be valid for the method call at 10:8... <anon>:10 arr.iter().map(|elem| (row, elem)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <anon>:10:24: 10:42 note: ...so that argument is valid for the call <anon>:10 arr.iter().map(|elem| (row, elem)) ^~~~~~~~~~~~~~~~~~ 

Here is the playpen link.

The problem seems to be related to the inability to infer the lifetime in the argument of closing the map method, although I'm not sure why.

  • Can someone explain the problem here a little more clearly?
  • Is it possible to create the desired iterator in another way?
+5
source share
2 answers

Even if this is not very clear, the compiler cannot determine the life of your inner closure.

 |elem| (row, elem) 

Since this closure captures the row from its environment (here it is the body of your outer closure), therefore, it should not survive it.

However, you are trying to return it to the Map<> object returned by .map(..) , and therefore have conflicting requirements: your inner closure is invited to survive an area that it cannot survive!

An easy way to avoid this problem is to make your inner closure accept row as an argument, and for this we can use:

  • repeat(..) , which creates an iterator that repeats the same element forever
  • .zip(..) iterator method that allows you to simultaneously promote two iterators

For something this way:

 let mut all_elems = mat.iter().enumerate().flat_map(|(row, arr)| { arr.iter() .zip(repeat(row)) .map(|(elem, my_row)| (my_row, elem)) }); 

But in this case, we can make it even simpler, since |(elem, my_row)| (my_row, elem) |(elem, my_row)| (my_row, elem) looks pretty useless:

 let mut all_elems = mat.iter().enumerate().flat_map(|(row, arr)| { repeat(row).zip(arr.iter()) }); 
+5
source

Another way to increase the lifetime of an internal circuit |elem| (row, elem) |elem| (row, elem) would mark it as a moving close by simply adding the keyword move . This will also compile:

 let all_elems = mat.iter().enumerate().flat_map(|(row, arr)| { arr.iter().map(move |elem| (row, elem)) }); 

The same behavior is observed when trying to return a closed (closed) closing function. The following function does not compile because the lifetime of the closure is related to the lifetime of the local variable row :

 fn foo_fail() -> Box<Fn(u32) -> (u32, u32)> { let row = 1; Box::new(|elem| (row, elem)) } 

Using a moving short circuit will work fine:

 fn foo_success() -> Box<Fn(u32) -> (u32, u32)> { let row = 1; Box::new(move |elem| (row, elem)) } 
+2
source

Source: https://habr.com/ru/post/1206967/


All Articles