我想使用 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/