我正在尝试编写一个简单的文本解析实用程序,用于
&str
。我想实现一个函数,该函数接受一个闭包对象和一个分隔符字符串,该字符串返回一个实现
Iterator
它不断调用闭包对象,并在每次调用时吃掉分隔符
next()
由于我不知道迭代项是什么类型(这取决于闭包),我想对此进行概括,所以它的签名将是
FnMut(&mut Parser) -> Option<T>
。由于它可以选择从解析器存储的字符串中借用,因此我需要插入适当的生命周期。
这是我目前所拥有的:
(
Link to Rust Playground
)
struct Parser<'a> {
string: &'a str,
}
impl<'a> Parser<'a> {
// ...
fn at_end(&self) -> bool {
// returns whether we're at the end of the string
false
}
fn expect(&mut self, _s: &str) -> &mut Self {
// expects the next part to be `s` and advances the string
// ...
self
}
fn parse_iter<'b, T: 'a, F: FnMut(&'a mut Self) -> Option<T>>(
&'a mut self,
separator: &'b str,
f: F,
) -> ParseIter<'a, 'b, T, F> {
ParseIter {
parser: self,
func: f,
sep: separator,
skip: false,
}
}
}
struct ParseIter<'a, 'b, T, F>
where
T: 'a,
F: FnMut(&'a mut Parser<'a>) -> Option<T>
{
parser: &'a mut Parser<'a>,
func: F,
sep: &'b str,
skip: bool,
}
impl<'a, 'b, T, F> Iterator for ParseIter<'a, 'b, T, F>
where
T: 'a,
F: FnMut(&'a mut Parser<'a>) -> Option<T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.parser.at_end() {
return None;
}
if std::mem::replace(&mut self.skip, true) {
self.parser.expect(self.sep);
}
(self.func)(self.parser) // error here!
}
}
调用闭包的最后一行代码会产生错误:
error: lifetime may not live long enough
--> util\src\parser.rs:156:9
|
140 | impl<'a, 'b, T, F> Iterator for ParseIter<'a, 'b, T, F>
| -- lifetime `'a` defined here
...
147 | fn next(&mut self) -> Option<Self::Item> {
| - let's call the lifetime of this reference `'1`
...
156 | (self.func)(self.parser)
| ^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
我的意思是,我甚至不明白错误的本质。显然,
&mut self
活不了多久
'a
因为它本身就是一个包含生命周期为的引用的对象
一
,那么怎么能
&mut自我
可能活得更久
一
?
但是,好吧,从表面上看,我想我需要确保
&mut自我
也是
一
。但我不能明确地命名它,因为
迭代器
特质。
我如何让我的代码编译?
我想还有一个次要问题,我一直在代码中添加明确的引用来试图解决这个问题。我能逃脱的明确引用的最小数量是多少?