rust - 功能性使用rust : Why is `filter` borrowing in closure?

标签 rust functional-programming

我正在尝试使用 Rust 的函数功能。

例如,我想转换这个循环:

levels: Vec<Vec<u8>> = //< Built by something

let mut total = 0;
for (x, y) in iproduct!(0..10, 0..10) {
    if levels[x][y] > 9 {
        total += count_something(levels, x, y);
    }
}

// Edit: here's the `count_something` function signature
fn count_something (levels: &mut Vec<Vec<u8>>, x: usize, y: usize) -> usize {
    // Count
}

这是我功能重构的结果:

iproduct!(0..10, 0..10)
    .filter(|(x, y)| levels[*x][*y] > 9)
    .map(|(x, y)| count_something(levels, x, y))
    .sum()

问题是:这段代码无法编译。
错误:error[E0500]:closure requires unique access to *levels but it has been borrowed.

我不明白为什么 filter 会借用 levels 2D 矩阵。
我对幕后发生的事情的心理模型似乎不够充分。

最佳答案

I don't see why filter borrows the levels 2D matrix. My mental model of what is happening under the hood seems inadequate.

filter 的回调需要 访问 矩阵,所以这里有一个借用(替代方案是移动):在 Rust 中,闭包是 a 的语法糖struct + 一个可调用的,任何自由变量都会自动转换为隐式匿名结构的成员:

.filter(|(x, y)| levels[*x][*y] > 9)

变成(或多或少,有很多被跳过)

struct $SECRET1$ {
    levels: &Vec<Vec<u8>>
}
impl $SECRET1$ {
    fn call(&self, x: &usize, y: &usize) -> bool {
        self.levels[*x][*y] > 9
    }
}
[...]
.filter($SECRET1$ { levels: &levels })

这就是 levels 被借用的原因。

问题的另一部分是为什么 map 运行时仍然借用levels,答案是Rust的迭代器是惰性的,所以它们同时运行操作(交错),而不是顺序。

所以当你写

iproduct!(0..10, 0..10)
    .filter(|(x, y)| levels[*x][*y] > 9)
    .map(|(x, y)| count_something(levels, x, y))
    .sum()

你真的在写这样的东西:

let p = iproduct!(0..10, 0..10);
let f = Filter {
    f: |(x, y)| levels[*x][*y] > 9,
    iter: p
};
let m = Map {
    f: |(x, y)| count_something(levels, x, y),
    iter: f
};
Iterator::sum(m)

你可以看到 Map.fFilter.f 同时存在并且需要相同的数据,如果两者都只需要就可以了从中读取,但显然 count_something(因此 map)需要一个可变(唯一)引用,这与只读(共享)引用不兼容。

关于rust - 功能性使用rust : Why is `filter` borrowing in closure?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70350553/

相关文章:

rust - `map` 调用在这里有什么作用吗?

java - Java 7 中的函数式编程

java - orElseGet 在 Optional<List<Entity>> 的情况下如何工作

javascript - 使用 DOM 操作时的纯函数

algorithm - 纯函数式编程的效率

rust - 如何在block_on节中交换数据?

reference - 在 RUST 中借用和捕获变量

rust - 是否可以指定异步函数结果的生存期?

generics - 如何打开任意数量的嵌套选项类型?

functional-programming - 仅在 fa() 成功时调用 fb() 的最惯用方法