【问题标题】:Why are predicates for Rust iterator's FnMut and not Fn?为什么 Rust 迭代器的 FnMut 是谓词而不是 Fn?
【发布时间】:2019-10-19 15:58:56
【问题描述】:

看看skip_whiletake_while 这样的谓词,它们是

skip_while<P>(self, predicate P) -> ...
  where Self: Sized, P: FnMut(&Self::Item) -> bool;

如果谓词只是返回真或假,而不修改值,为什么它必须是FnMut 而不是Fn(如Fn(&amp;Self::Item) -&gt; bool)?

【问题讨论】:

  • 这样你就可以在你的闭包中有一个状态。 FnMut 意味着它可以改变它的状态play.rust-lang.org/…。正如 doc 所说“当您想要接受类似函数类型的参数并且需要重复调​​用它时,使用 FnMut 作为边界,同时允许它改变状态。如果您不希望参数改变状态,请使用 Fn 作为一个界限;如果您不需要重复调​​用它,请使用 FnOnce。" doc.rust-lang.org/std/ops/trait.FnMut.html

标签: rust iterator predicate type-signature


【解决方案1】:

FnMut 中的Mut 表示谓词可以具有可变状态。它没有说明参数。

另外,FnMutFn 的超特征,因此您也可以传递Fn,其中FnMut 被接受。

作为一个愚蠢的例子,考虑这个存储状态的闭包(因此是FnMut,但不是Fn),但不能修改迭代器中的元素:

fn main() {
    let v = vec![1, 2, 3, 4, 0, 5, 6, 7];

    println!("{:?}", v.iter().skip_while(|&&v| v != 0).collect::<Vec<_>>());

    let mut state = false;
    let one_after_zero = |&&v: &&u32| {
        if state {
            false
        } else if v == 0 {
            state = true;
            true
        } else {
            true
        }
    };

    println!("{:?}", v.iter().skip_while(one_after_zero).collect::<Vec<_>>());
}

(Permalink to the playground)

输出:

[0, 5, 6, 7]
[5, 6, 7]

【讨论】:

猜你喜欢
  • 2021-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 2011-10-04
  • 2021-08-01
相关资源
最近更新 更多