以下是Rust by Example的示例:
pub trait Iterator {
// The type being iterated over.
type Item;
// `any` takes `&mut self` meaning the caller may be borrowed
// and modified, but not consumed.
fn any<F>(&mut self, f: F) -> bool where
// `FnMut` meaning any captured variable may at most be
// modified, not consumed. `Self::Item` states it takes
// arguments to the closure by value.
F: FnMut(Self::Item) -> bool {}
}
如果参数是按值获取的话,为什么还要使用FnMut
,因为参数不能被突变?事实上,为什么FnMut
在这里被允许?它似乎只有FnOnce
is permitted to do this:
已经注意到Rust选择如何捕获变量 飞没有注释。这在正常使用中非常方便 但是在编写函数时,不允许这种歧义。该 闭包的完整类型,包括哪种捕获类型,必须是 注释。闭包使用的捕获方式被注释为其中之一 以下
trait
s:
- 获取捕获
Fn
:通过引用(&T
)- 获取捕获
FnMut
:通过可变引用(&mut T
)- 获取捕获
FnOnce
:按值(T
)
答案 0 :(得分:4)
FnOnce
,FnMut
和Fn
之间的区别是函数如何访问其环境(分别为move,mutable reference,shared reference)。它与访问函数的参数无关。
FnMut
,因为any
方法可能需要多次调用该函数。
有一个paragraph in the Rust book about the implementation of closures。它显示了self
参数的差异,它基本上是包含环境的struct
。
答案 1 :(得分:1)
如果参数是按值获取的话,为什么还要使用FnMut,因为arg无法进行变异?
您链接的示例有点不正确,因为方法定义应如下所示:
import com.sun.jna.NativeLibrary;
但是,此更改不会更改fn any<F>(&mut self, mut f: F) -> bool // note the `mut f: F`
where F: FnMut(Self::Item) -> bool {}
方法的使用方式! any
仅仅是变量绑定的一部分(仅对方法impl很重要)而不是类型的一部分。按值获取某些东西可以让我们完全控制变量 - 如果我们想要改变变量,我们可以这样做,但我们必须可变地绑定它。
事实上,为什么FnMut甚至被允许在这里?
您可以拥有 允许使用某种类型的所有类型操作的特征界限,即使由于缺少对该变量的访问权限而无法使用这些操作。参见:
mut
这是有效的,但没有用,因为只要你想对迭代器做一些可用的事情(比如调用fn foo<T: Iterator<Item=i32>>(it: &T) {}
):
next
您将收到编译器错误,因为您无法在不可变借位上调用it.next();
方法。因此,您链接的示例仅起作用,因为函数体不使用&mut self
的功能。