在 Rust 中,为什么 FnOnce 可以改变值?

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

我一直将

FnOnce
视为一个可以在其范围内消耗值但不能变异的函数,那就是
FnMut
并且你需要一个
mut
闭包来执行类似的操作。

然而,这个例子似乎有效:

#[derive(Copy, Debug, Clone)]
struct Thing(u8);

fn thing<T>(closure: T) -> Result<Thing, ()> where T: FnOnce() -> Result<Thing, ()> {
    closure()
}

fn main() {
    let mut a = None;
    let b = || {
        a = Some(Thing(8));
        a.ok_or_else(|| panic!("yo"))
    };
    let c = thing(b).unwrap();
    println!("{a:?}");
    println!("{c:?}");
}

和打印:

Some(Thing(8))
Thing(8)

实际上,如果将非 mut 闭包强制转换为 FnOnce 并且仅使用一次,则非 mut 闭包可以改变其环境中的可变变量。为什么 Rust 不在这里强制执行 FnMut 和可变闭包?我很困惑。

rust closures
1个回答
0
投票

在我看来,文档中的措辞“消耗捕获的变量”有点不幸。可以这样想:A

Fn
可以借用它的环境;
FnMut
可以可变地借用其环境;并且 FnOnce
 可以拥有其环境的所有权。在 Rust 中,如果你拥有一个值,你就可以改变它。它们是彼此的亚型。 
FnMut
 可以做 
Fn
 可以做的任何事情 
甚至更多FnOnce
 可以做任何 
FnMut
 可以做的事情 
甚至更多

© www.soinside.com 2019 - 2024. All rights reserved.