gpt4 book ai didi

rust - 当某些值被忽略时,如何避免迭代器实现中不必要的昂贵操作?

转载 作者:行者123 更新时间:2023-12-03 11:28:25 25 4
gpt4 key购买 nike

我有一个Iterator实现,如下所示:

struct MyType {
// stuff
}

struct Snapshot {
// stuff
}

impl MyType {
pub fn iter(&mut self) -> MyIterator {
MyIterator {
foo: self
}
}
}

struct MyIterator<'a> {
foo: &'a mut MyType
}

impl<'a> Iterator for MyIterator<'a> {
type Item = Snapshot;

fn next(&mut self) -> Option<Self::Item> {
if self.cheap_condition() {
self.cheap_mutation(); // Inexpensive
let s: Snapshot = self.snapshot(); // Expensive copying
Some(s)
} else {
None
}
}
}
如果我想使用生成的 Snapshot的每个实例,这都可以很好地工作,但是如果我想使用类似 Iterator::step_byIterator::last的东西,而我不在乎中间的 Snapshot s,则生成这些未使用的值所产生的成本是巨大的性能打击。
我可以重写 Iterator的每个方法,以便仅在必要时才进行昂贵的操作,但是我觉得必须有一种更简单,更惯用的方式来做到这一点,或者是一种懒惰地生成与 Snapshot对应的迭代方式如果尚未再次调用 Item,则为 Iterator::next的中间类型。
我不想返回对 MyType的引用,因为我希望我确实生成的 Snapshot具有独立的生存期,例如,使 Iterator::collect()的结果可以超过 MyType实例的生命周期。

最佳答案

您不必重写每个Iterator方法。唯一相关的是nthlastcountstep_byskip。所有其他方法都需要以某种方式检查Self::Item,因此您无法避免为这些生成Snapshot。幸运的是,step_byskip在内部使用nth,因此实际上只剩下nthcountlast,我们必须对其进行覆盖:

use core::marker::PhantomData;

struct Snapshot;

struct MyType<'a> {
item: PhantomData<&'a ()>,
}

impl<'a> MyType<'a> {
fn cheap_condition(&self) -> bool {
todo!()
}
fn cheap_mutation(&mut self) {
todo!()
}
fn snapshot(&self) -> Snapshot {
Snapshot
}
}

impl<'a> Iterator for MyType<'a> {
type Item = Snapshot;

fn next(&mut self) -> Option<Self::Item> {
if self.cheap_condition() {
self.cheap_mutation(); // Inexpensive
Some(self.snapshot()) // Expensive
} else {
None
}
}

// also covers skip & step_by methods
fn nth(&mut self, n: usize) -> Option<Self::Item> {
for _ in 0..n {
if self.cheap_condition() {
self.cheap_mutation();
} else {
return None;
}
}
self.next()
}

fn count(mut self) -> usize
where
Self: Sized,
{
let mut count: usize = 0;
while self.cheap_condition() {
self.cheap_mutation();
count += 1;
}
count
}

fn last(mut self) -> Option<Self::Item>
where
Self: Sized,
{
while self.cheap_condition() {
self.cheap_mutation();
if !self.cheap_condition() {
return Some(self.snapshot());
}
}
None
}
}
playground
如果您想通过检查 Iterator而不是 filter的谓词来使诸如 MyType<'a>的其他 Snapshot方法变得懒惰,则必须为此定义自己的类似于 Iterator的特征,因为所有其他方法仅适用于 Self::Item

关于rust - 当某些值被忽略时,如何避免迭代器实现中不必要的昂贵操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66141933/

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