Bos*_*osh 5 iterator traits rust borrow-checker
我想使用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")
Run Code Online (Sandbox Code Playgroud)
我在这里创造了一个MCVE,但是我得到了:
:10:5:10:19错误:无法移出借来的内容:10 chars.by_ref().cautious_take_while(|&x | x!='.');
据我所知,TakeWhile在我的函数签名方面,我遵循与Rust自己相同的模式,但我看到了与借用检查器不同的不同行为.有人可以指出我做错了吗?
有趣的by_ref()是它返回一个对自身的可变引用:
pub trait IteratorExt: Iterator + Sized {
fn by_ref(&mut self) -> &mut Self { self }
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理是因为为Iterator类型Iterator的可变指针实现了特性.聪明!
impl<'a, I> Iterator for &'a mut I where I: Iterator, I: ?Sized { ... }
Run Code Online (Sandbox Code Playgroud)
标准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,}
}
}
Run Code Online (Sandbox Code Playgroud)
这个解决方案的一个奇怪的副作用是现在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;
}
Run Code Online (Sandbox Code Playgroud)
其余的或多或少是直截了当的.
| 归档时间: |
|
| 查看次数: |
362 次 |
| 最近记录: |