gpt4 book ai didi

iterator - 为什么 Fuse 迭代器适配器没有按预期工作?

转载 作者:行者123 更新时间:2023-11-29 07:50:51 25 4
gpt4 key购买 nike

我正在试验 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),然后是 Nonei2 是用 fuse() 改编的同一个迭代器。 Fuse 应使其在第一个 None 之后返回 None,并且由于它返回的第一个值是 None,这应该是它返回的唯一值。但是,它的行为与 i1 相同。我做错了什么?

最佳答案

TL;DR 摘要:这 was a bug并在 Rust 1.19 及更新版本中得到修复。

我很确定你没有做错任何事。这似乎是一个错误(我的猜测)或一个非常令人困惑的交互。查看这个扩展示例:

#![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 并开始返回Nonescan 将继续返回。然而,这并不是获得 None 的唯一方法——闭包 也可以返回 None!

关于iterator - 为什么 Fuse 迭代器适配器没有按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43947111/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com