为什么 sort_by_key 函数需要类型为 FnMut 的闭包,而不是 Fn?

4

我刚开始学习Rust编程,并阅读了Rust书籍中的闭包章节。书中提到sort_by_key函数需要FnMut类型的闭包,但是我想知道如果sort_by_key函数捕获的项没有被闭包改变,为什么不能将其改为Fn类型?


1
这样可以编写更加灵活的代码。请注意,FnMut不会改变其参数,而是会改变其捕获的环境。因此,它可以接受比Fn更多的闭包函数。 - Aleksander Krauze
1
进一步解释Alexander所说的,显然FnOnce无法工作,因为sort_by_key需要调用闭包不止一次。这就使得FnMut成为最灵活的选择。 - PitaJ
@PitaJ OP问为什么Fn不起作用,但是你的评论解释了为什么FnOnce不起作用,显然这是行不通的。 - Haris Muzaffar
@AleksanderKrauze,您能否分享一个例子,说明当您说FnMut不会改变其参数,而是改变其捕获的环境时,它的闭包如何改变其捕获环境?换句话说,sort_by_key的闭包如何改变其捕获环境? - Haris Muzaffar
1个回答

1

FnMutFn的超级特性。这意味着任何Fn的实例都可以在期望FnMut的地方使用。

也许可以通过下面这个来自FnMut文档的示例来解释一下:

fn do_twice<F>(mut func: F)
where F: FnMut()
{
    func();
    func();
}

fn main() {
    let mut x: usize = 1;
    {
        let add_two_to_x = || x += 2;
        do_twice(add_two_to_x);
        let print_stuff = || println!("Awesome!");        
        do_twice(print_stuff);
    }
    println!("{x}");  
}

请注意在上面的例子中,add_two_to_x 需要 FnMut 才能工作,而不能使用 Fn,而print_stuff 则两者都可以使用。
因此,使用 FnMut 时(作为使用者),您有自由设计一个可以修改其环境的闭包,但并非必须这样做。而使用 Fn 时则会更加受限制。

1
很明显,FnMutFn 的超集,但是 sort_by_key 的闭包似乎并没有改变它的环境,这清楚地表明它根本不需要 FnMut - Haris Muzaffar
sort_by_key 接受 FnMut,这意味着如果需要,您可以传递一个修改该闭包捕获环境的闭包。 - PitaJ
我明白你的意思。谢谢。 - Haris Muzaffar
@PitaJ 你有一个例子可以展示在sort_by_key中传递一个会改变捕获值的闭包吗?对我来说,这看起来像是一种代码异味,更合理的做法是防止这种情况发生,但也许有一些我没有考虑到的合法用例。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接