我一直将
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 和可变闭包?我很困惑。
在我看来,文档中的措辞“消耗捕获的变量”有点不幸。可以这样想:A
Fn
可以借用它的环境; FnMut
可以可变地借用其环境;并且 FnOnce
可以拥有其环境的所有权。在 Rust 中,如果你拥有一个值,你就可以改变它。它们是彼此的亚型。
FnMut
可以做
Fn
可以做的任何事情甚至更多;
FnOnce
可以做任何
FnMut
可以做的事情甚至更多。