Why doesn't the Fuse adapter adapter work properly?

I am experimenting with an iterator adapter Fuseand getting unexpected results ( link to the playing field ):

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!("");
}

What prints:

None
Some(2)
None

None
Some(2)
None

The iterator i1returns what I expect. It returns None, then Some(2), then None. i2is the same iterator adapted from fuse(). The fuse should return Noneafter the first None, and since the first return value is equal None, this should be the only value that it returns. However, he behaves the same way i1. What am I doing wrong?

+4
source share
1 answer

, . ( ), . :

#![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());
}

, FusedIterator - , . Iterator::fuse , -op.

, :

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

, FusedIterator None, scan None. None - None!

+4

Source: https://habr.com/ru/post/1677040/


All Articles