为什么Fuse迭代器适配器不能按预期工作?

win*_*ner 5 iterator rust

我正在尝试使用Fuse迭代器适配器并获得意外结果(Playground链接):

fn main() {
    let mut i1 = (1..3).scan(1, |_, x| {
        if x < 2 { None } else { Some(x) }
    });
    println!("{:?}", i1.next());
    println!("{:?}", i1.next());
    println!("{:?}", i1.next());
    println!("");

    let mut i2 = (1..3).scan(1, |_, x| {
        if x < 2 { None } else { Some(x) }
    }).fuse();
    println!("{:?}", i2.next());
    println!("{:?}", i2.next()); // This should print None
    println!("{:?}", i2.next());
    println!("");
}
Run Code Online (Sandbox Code Playgroud)

哪个印刷品:

None
Some(2)
None

None
Some(2)
None
Run Code Online (Sandbox Code Playgroud)

迭代器i1正在回归我的期望.它返回None,然后Some(2),然后None.i2是同样的迭代器适应fuse().保险丝应该None在第一个之后返回None,因为它返回的第一个值None应该是它返回的唯一值.但是,它的行为与...相同i1.我究竟做错了什么?

She*_*ter 5

我很确定你做错了什么.这似乎是一个错误(我的猜测)或一个非常令人困惑的互动.看看这个扩展的例子:

#![feature(fused)]

fn dump<I: Iterator<Item = i32>>(label: &str, mut iter: I) {
    println!("= Running: {}", label);
    for _ in 0..10 {
        println!("{:?}", iter.next());
    }
    println!("");
}

fn boxed_internal_fuse() -> Box<Iterator<Item = i32>> {
    Box::new((1..3)
        .scan(1, |_, x| if x < 2 { None } else { Some(x) })
        .fuse())
}

fn boxed_no_fuse() -> Box<Iterator<Item = i32>> {
    Box::new((1..3)
        .scan(1, |_, x| if x < 2 { None } else { Some(x) }))
}

use std::iter::FusedIterator;
fn boxed_no_fuse_but_fused() -> Box<FusedIterator<Item = i32>> {
    Box::new((1..3)
        .scan(1, |_, x| if x < 2 { None } else { Some(x) }))
}

fn main() {
    let i1 = (1..3)
        .scan(1, |_, x| if x < 2 { None } else { Some(x) });
    dump("Scan", i1);

    let i2 = (1..3)
        .scan(1, |_, x| if x < 2 { None } else { Some(x) })
        .fuse();
    dump("Fuse<Scan>", i2);

    dump("Box<Fuse<Scan>>", boxed_internal_fuse());
    dump("Fuse<Box<Iterator>>", boxed_no_fuse().fuse()); // All `None`s
    dump("Fuse<Box<FusedIterator>>", boxed_no_fuse_but_fused().fuse());
}
Run Code Online (Sandbox Code Playgroud)

诀窍在于,这FusedIterator是一种旨在提高效率的不稳定特征.它让我们Iterator::fuse知道这是一个无操作.

但是,在这种情况下,条件是必要的但不充分:

impl<B, I, St, F> FusedIterator for Scan<I, St, F>
    where I: FusedIterator, F: FnMut(&mut St, I::Item) -> Option<B> {}
Run Code Online (Sandbox Code Playgroud)

确实如果底层迭代器FusedIterator并且开始返回None,scan将继续返回None.然而,这不是获得的唯一途径None- 关闭也可以返回None!