Vec 上的迭代器<Vec<i32>>:闭包可能比当前函数寿命更长,但它借用了

问题描述 投票:0回答:1

我正在编写一个函数来处理

Vec<Vec<i32>>

fn process_grid(grid: Vec<Vec<i32>>) -> Vec<i32> {
    grid.iter()
        .enumerate()
        .flat_map(|(i, row)| {
            row.iter()
                .enumerate()
                 // closure may outlive the current function, 
                 // but it borrows `i`, which is owned by the current function
                .flat_map(|(j, val)| process(i, j, *val))
        })
        .collect()
}

fn process(i: usize, j: usize, val: i32) -> Option<i32> {
    todo!()
}

完整的编译错误如下所示:

error[E0373]: closure may outlive the current function, but it borrows `i`, which is owned by the current function
   --> src/main.rs:291:27
    |
291 |                 .flat_map(|(j, val)| process(i, j, *val))
    |                           ^^^^^^^^^^         - `i` is borrowed here
    |                           |
    |                           may outlive borrowed value `i`
    |
note: closure is returned here
   --> src/main.rs:289:13
    |
289 | /             row.iter()
290 | |                 .enumerate()
291 | |                 .flat_map(|(j, val)| process(i, j, *val))
    | |_________________________________________________________^
help: to force the closure to take ownership of `i` (and any other referenced variables), use the `move` keyword
    |
291 |                 .flat_map(move |(j, val)| process(i, j, *val))
    |                           ++++

添加

move
关键字确实可以使事情正常工作,但它并没有明确说明为什么它不移动就无法编译。


封闭物

|(j, val)| process(i, j, *val)
怎么可能比其封闭的封闭物寿命更长:

|(i, row)| {
    row.iter()
        .enumerate()
        // closure may outlive the current function, 
        // but it borrows `i`, which is owned by the current function
        .flat_map(|(j, val)| process(i, j, *val))
}

也许在这里放置明确的生命周期会有帮助?

rust closures lifetime borrow-checker
1个回答
0
投票

编译器选择仅使用相关闭包 references

i
,并且由于这是通过引用捕获的并且迭代器是惰性的,因此这将有效地尝试从外部
i
闭包返回对
flat_map
的引用,这是不允许的,因为
i
仅适用于该调用。

在这种情况下,通过添加 move 关键字来告诉编译器将

move
捕获到闭包中就足够了,如下所示:

fn process_grid(grid: Vec<Vec<i32>>) -> Vec<i32> {
    grid.iter()
        .enumerate()
        .flat_map(|(i, row)| {
            row.iter()
                .enumerate()
                .flat_map(move |(j, val)| process(i, j, *val))
                //        ^^^^
        })
        .collect()
}
© www.soinside.com 2019 - 2024. All rights reserved.