use std::iter::Peekable;
pub trait AdvanceWhile<I: Iterator> {
fn advance_while<P>(&mut self, predicate: P)
where
P: Fn(&I::Item) -> bool;
}
impl<I: Iterator> AdvanceWhile<I> for Peekable<I> {
fn advance_while<P>(&mut self, predicate: P)
where
P: Fn(&I::Item) -> bool,
{
while let Some(val) = self.peek() {
if predicate(val) {
self.next();
} else {
break;
}
}
}
}
错误:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:16:17
|
14 | while let Some(val) = self.peek() {
| ---- first mutable borrow occurs here
15 | if predicate(val) {
16 | self.next();
| ^^^^ second mutable borrow occurs here
...
20 | }
| - first borrow ends here
答案 0 :(得分:3)
词汇借用的典型案例:编译器尚不能理解这是代码是安全的。因此,暂时(直到实施所谓的非词汇借用),尝试重写您的代码。像这样,例如:
fn advance_while<P>(&mut self, predicate: P)
where P: Fn(&I::Item) -> bool
{
loop {
if let Some(val) = self.peek() {
if !predicate(val) {
break;
}
} else {
break;
}
self.next();
}
}
答案 1 :(得分:3)
正如Lukas Kalbertodt已经说过,这是借阅检查员的限制。在这里,我想展示一个更易读的版本:
fn advance_while<P>(&mut self, predicate: P)
where P: Fn(&I::Item) -> bool
{
while let Some(true) = self.peek().map(&predicate) {
self.next();
}
}
答案 2 :(得分:1)
您可以将此功能重写为:
impl<I: Iterator> AdvanceWhile<I> for Peekable<I> {
fn advance_while<P>(&mut self, predicate: P)
where P: Fn(&I::Item) -> bool
{
loop {
{
let peek = match self.peek() {
Some(p) => p,
None => break,
};
if !predicate(peek) {
break;
}
}
self.next();
}
}
}
答案 3 :(得分:1)
问题是您的原始代码可以执行此操作:
while let Some(val) = self.peek() {
if predicate(val) {
self.next();
println!("{:?}", val);
} else {
break;
}
}
调用val
后访问next()
将允许您访问不再有效的内存,从而导致内存不安全。
正如其他人所指出的,你的代码并没有实际这样做,但是当前的Rust使用 lexical lifetimes ,这是一个过于保守的近似值参考需要有效。 Future Rust应该有助于限制逻辑,而不会引起不安全。
如果您的值实现Copy
,您可以使用它:
fn advance_while<P>(&mut self, predicate: P)
where
P: Fn(&I::Item) -> bool,
I::Item: Copy,
{
while let Some(&val) = self.peek() {
if predicate(&val) {
self.next();
} else {
break;
}
}
}
这会导致从peek
返回的引用中复制值。由于没有任何借用,你要改变迭代器的事实不会引起问题。
如果您的类型实现Clone
,您可以克隆该值,再次取消它的关联:
fn advance_while<P>(&mut self, predicate: P)
where
P: Fn(&I::Item) -> bool,
I::Item: Clone,
{
while let Some(val) = self.peek().cloned() {
if predicate(&val) {
self.next();
} else {
break;
}
}
}
如果您的类型既不是Copy
也不是Clone
,则需要为布尔结果引入临时变量。这清楚地告诉编译器,除了等式检查语句之外,peek
返回的借用是不需要的:
fn advance_while<P>(&mut self, predicate: P)
where
P: Fn(&I::Item) -> bool,
{
while self.peek().map_or(false, &predicate) {
self.next();
}
}
另见:
答案 4 :(得分:0)
好的,所以这不是最好的方法,但对于更复杂的案例,它可能会派上用场......
fn advance_while<P>(&mut self, predicate: P)
where P: Fn(&I::Item) -> bool
{
while {
if let Some(val) = self.peek() {
predicate(val)
} else {
false
}
}
{
self.next();
}
}