为什么Fn是从FnMut(它又来源于FnOnce)派生而来的?

9
如果您查看官方Rust文档,您会发现trait Fn是从FnMut派生的,也就是说,要实现Fn,您必须先实现FnMut(然后再实现FnOnce,因为FnMut也从它派生出来)。
这是为什么呢?我无法理解。是因为您可以将每个Fn都视为FnOnceFnMut吗?
2个回答

5
这里最好的参考是优秀的在Rust中找到闭包博客文章。我将引用其中的关键部分:
引用块: 有三个特征和七个可能实现非空特征集...但实际上只有三个有趣的配置:
Fn,FnMut和FnOnce, FnMut和FnOnce, 仅 FnOnce。
为什么?因为这三个闭包特征实际上是三个嵌套集:实现 Fn 的每个闭包也可以实现 FnMut (如果&self工作,则&mut self 也可以使用;证明:&*self ),同样,实现 FnMut 的每个闭包也可以实现 FnOnce 。这种层次结构在类型级别上强制执行

我决定在我的任务中使用IndexMut而不是FnMut,但我认为我发现了一个错误?因为对于函数,有(FnOnce), (FnOnce, FnMut), (FnOnce, FnMut, Fn)。好的,我明白了。但是对于索引,它是:(Index), (Index, IndexMut)。这是相反的,我认为这是一个错误,因为当我实现可变版本时,我也必须拥有不可变版本,否则无法工作...(我应该为此打开一个新问题还是这个评论就足够了?) - Kapichu
@Kapichu,对我来说,这听起来像是一个不同的问题。具体来说,我想问你“哪个不起作用”是什么意思。我敢打赌这需要一段代码片段,这意味着这可能是另一个问题。更多的问题是好的——对未来的人来说,可以得到更细粒度的搜索结果。 - Shepmaster
好的,我会做到的,这个问题的答案对我很有帮助!谢谢! - Kapichu

0
当一个函数需要FnMut作为输入,但是你的闭包只实现了Fn时,你的闭包就不能成为该函数的输入。这不够灵活。

每个实现了Fn的闭包也可以实现FnMut

编译器会自动为那些能够实现Fn的闭包实现FnMut和FnOnce。因此,这些闭包可以用于需要Fn或FnMut或FnOnce作为输入的函数中。

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