gpt4 book ai didi

iterator - 使用 Peekable 实现 "cautious"take_while

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

我想使用 Peekable作为新cautious_take_while的基础类似于take_while 的操作来自 IteratorExt但不消耗第一个失败的项目。 (有一个附带的问题,即这是否是一个好主意,以及是否有更好的方法在 Rust 中实现这个目标——我很乐意得到这方面的提示,但主要是我试图了解我的代码在哪里破)。

我尝试启用的 API 基本上是:

let mut chars = "abcdefg.".chars().peekable();

let abc : String = chars.by_ref().cautious_take_while(|&x| x != 'd');
let defg : String = chars.by_ref().cautious_take_while(|&x| x != '.');

// yielding (abc = "abc", defg = "defg")

我已经破解了 creating a MCVE here ,但我得到:

:10:5: 10:19 error: cannot move out of borrowed content:10 chars.by_ref().cautious_take_while(|&x| x != '.');

据我所知,我正在遵循与 Rust 自己的 TakeWhile 相同的模式就我的函数签名而言,但我从借用检查器中看到了不同的行为。有人可以指出我做错了什么吗?

最佳答案

关于 by_ref() 的有趣之处是它返回对自身的可变引用:

pub trait IteratorExt: Iterator + Sized {
fn by_ref(&mut self) -> &mut Self { self }
}

之所以有效,是因为 Iterator trait 是为指向迭代器的可变指针 类型实现的。聪明!

impl<'a, I> Iterator for &'a mut I where I: Iterator, I: ?Sized { ... }

标准take_while函数之所以有效,是因为它使用了特征 Iterator , 即自动解析为 &mut Peekable<T> .

但是你的代码不工作因为Peekable是一个结构,而不是一个特征,所以你的 CautiousTakeWhileable必须指定类型,并且您正试图取得它的所有权,但您不能,因为您有一个可变指针。

解决办法,不带一个Peekable<T>但是&mut Peekable<T> .您还需要指定生命周期:

impl <'a, T: Iterator, P> Iterator for CautiousTakeWhile<&'a mut Peekable<T>, P>
where P: FnMut(&T::Item) -> bool {
//...
}

impl <'a, T: Iterator> CautiousTakeWhileable for &'a mut Peekable<T> {
fn cautious_take_while<P>(self, f: P) -> CautiousTakeWhile<&'a mut Peekable<T>, P>
where P: FnMut(&T::Item) -> bool {
CautiousTakeWhile{inner: self, condition: f,}
}
}

这个解决方案的一个奇怪的副作用是现在 by_ref不需要,因为 cautious_take_while()采用可变引用,因此它不会窃取所有权。 by_ref() take_while() 需要打电话因为它可以采取 Peekable<T>&mut Peekable<T> , 它默认为第一个。随着by_ref()调用它将解析为第二个。

现在我终于明白了,我认为更改 struct CautiousTakeWhile 的定义可能是个好主意将可窥视位包含到结构本身中。困难在于必须手动指定生命周期,如果我是对的话。像这样的东西:

struct CautiousTakeWhile<'a, T: Iterator + 'a, P> 
where T::Item : 'a {
inner: &'a mut Peekable<T>,
condition: P,
}
trait CautiousTakeWhileable<'a, T>: Iterator {
fn cautious_take_while<P>(self, P) -> CautiousTakeWhile<'a, T, P> where
P: FnMut(&Self::Item) -> bool;
}

剩下的就比较简单了。

关于iterator - 使用 Peekable 实现 "cautious"take_while,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28776630/

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