我试图从一个创建每个元素的函子中生成一个二维矩阵,并将其存储为一个平面Vec(每行连接).

我使用嵌套map(实际上是flat_map和嵌套map)来创建每一行并将其连接起来.Here is what I tried:

fn make<T, F>(n: usize, m: usize, f: F) -> Vec<T>
where
    F: Fn(usize, usize) -> T,
{
    (0..m).flat_map(|y| (0..n).map(|x| f(x, y))).collect()
}

fn main() {
    let v = make(5, 5, |x, y| x + y);

    println!("{:?}", v);
}

不幸的是,我在编译过程中遇到了一个错误:

error[E0597]: `y` does not live long enough
 --> src/main.rs:5:45
  |
5 |     (0..m).flat_map(|y| (0..n).map(|x| f(x, y))).collect()
  |                                    ---      ^ -          - borrowed value needs to live until here
  |                                    |        | |
  |                                    |        | borrowed value only lives until here
  |                                    |        borrowed value does not live long enough
  |                                    capture occurs here

如何在嵌套映射中使用闭包?我研究了这个问题,但我仍然对答案感兴趣.

推荐答案

在您的例子中,内部闭包|x| f(x,y)是borrow 闭包,它通过引用获取其环境(yf).

按照.flat_map(..)的工作方式,它禁止您保留对y的引用,这不是外部范围.因此,我们需要让你的闭包按价值来衡量它的环境,这对于yusizeCopy不是一个问题:

(0..m).flat_map(|y| (0..n).map(move |x| f(x, y))).collect()

然而,现在又出现了另一个问题:

error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
 --> src/main.rs:5:36
  |
1 | fn make<T, F>(n: usize, m: usize, f: F) -> Vec<T>
  |                                   - captured outer variable
...
5 |     (0..m).flat_map(|y| (0..n).map(move |x| f(x,y))).collect()
  |                                    ^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure

在这里,我们试图将f也移动到闭包中,这是绝对不可能的(除非m1,但编译器无法知道).

既然fFn(usize, usize) -> T,我们也可以显式地将&引用传递给它,&引用就是Copy:

fn make<T, F>(n: usize, m: usize, f: F) -> Vec<T>
where
    F: Fn(usize, usize) -> T,
{
    let f_ref = &f;
    (0..m)
        .flat_map(|y| (0..n).map(move |x| f_ref(x, y)))
        .collect()
}

在本例中,闭包按值获取其环境,该环境由yf_ref组成,两者都是Copy,一切正常.

Rust相关问答推荐

在Rust中创建可变片段的可变片段的最有效方法是什么?

有没有办法在Rust中配置常量变量的值?

如何将像烫手山芋一样不透明的值从一个Enum构造函数移动到下一个构造函数?

Tokio_Postgres行上未显示退回特性的生存期,且生命周期 不够长

无法定义名为&new&的关联函数,该函数的第一个参数不是self

RUST应用程序正在退出,错误代码为:(退出代码:0xc0000005,STATUS_ACCESS_VIOLATION)

作为1字节位掩码的布尔值 struct

Rust 的多态现象.AsRef与Derf

异步函数返回的future 生存期

对reqwest提供的这种嵌套JSON struct 进行反序列化

为相同特征的特征对象使用 move 方法实现特征

使用启用优化的 alloc 会导致非法指令崩溃

缺失serde的字段无法设置为默认值

我什么时候应该使用特征作为 Rust 的类型?

Rust 中的方法调用有什么区别?

只有一个字符被读入作为词法分析器的输入

从 Cranelift 发出 ASM

当特征函数依赖于为 Self 实现的通用标记特征时实现通用包装器

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的

为什么我可以在没有生命周期问题的情况下内联调用 iter 和 collect?