如果参数是按值取的,为什么还要使用`FnMut`?

时间:2016-03-25 13:53:41

标签: closures rust

以下是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
  • 获取捕获   

2 个答案:

答案 0 :(得分:4)

FnOnceFnMutFn之间的区别是函数如何访问其环境(分别为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;

(比较the std implementation

但是,此更改不会更改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的功能。