我尝试使用Fuse
迭代器适配器并获得意外结果(Playground link):
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!("");
}
打印哪些:
None
Some(2)
None
None
Some(2)
None
Iterator i1
正在回归我的期望。它返回None
,然后是Some(2)
,然后是None
。 i2
与fuse()
一致的迭代器相同。保险丝应该在第一个None
之后返回None
,并且因为它返回的第一个值是None
,它应该是它返回的唯一值。但是,它的行为与i1
相同。我做错了什么?
答案 0 :(得分: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());
}
诀窍是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> {}
如果底层迭代器为FusedIterator
并且开始返回None
,scan
将继续返回None
。但是,这不是获取None
的唯一方法 - 闭包也可以返回None
!