我正在研究Rust中的一个小词法分析器。我有想法将lexing阶段放入Iterator
特征的实现中。
struct Lexer {
text: String
}
impl Iterator for Lexer {
...
fn next(&mut self) -> Option<LexItem>{
....
// slicing issue
self.text = self.text[i .. self.text.len()]
}
}
我完全没有完全了解终身管理。我可以通过为text
属性定义具有生命周期的结构,这将(可能)使子操作更容易。然而,我没有在我的代码中加入这样的生命周期。另一方面,我很难将切片self.text[i .. .....]
再次转换为String
(如果可能的话,不知道)。
我尝试了以下修改:
struct Lexer<'a> {
text: &'a str
}
impl<'a> Iterator for Lexer<'a> {
...
fn next(&'a mut self) -> Option<LexItem>{
....
// slicing issue
self.text = self.text[i .. self.text.len()]
}
}
我收到错误:
src/lexer.rs:64:5: 81:6 error: method `next` has an incompatible type for trait: expected bound lifetime parameter , found concrete lifetime [E0053]
我试过的其他实现
impl<'a> Iterator for Lexer<'a> {
...
fn next<'b>(&'b mut self) -> Option<LexItem>{
....
// slicing issue
self.text = self.text[i .. self.text.len()]
}
}
src/lexer.rs:66:21: 66:52 error: mismatched types: expected `&'a str`, found `str` (expected &-ptr, found str) [E0308] src/lexer.rs:66 self.text = self.text[i .. self.text.len()]; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我认为这样的事情应该有效,因为我只会处理受体。
答案 0 :(得分:3)
(顺便说一下:foo[i..foo.len()]
应始终等同于foo[i..]
。)
如果self.text[i..]
类型为str
或self.text
,则String
的类型为未归类型&str
。为了使其大小(因此,为了使其工作),您需要将其转换为与text
相同的类型。
如果text
为String
,可以通过在切片结果上调用.to_string()
来完成此操作;将自动引用,使其合法。因此,self.text = self.text[i..].to_string();
。 (std::borrow::ToOwned::to_owned
也可以使用,效率稍高。)
如果text
为&str
,则只需使用&
为切片操作添加前缀,使其根据需要采用参考:self.text = &self.text[i..];
。
对于整个一生的事情,请阅读我对https://stackoverflow.com/a/24575591/497043的回答;它解释了fn next(&'a mut self)
等问题。
在我看来,你希望整个事情基于字符串切片(&str
),而不是拥有字符串(String
)。前者适用于迭代器(参见上述答案),而后者则不适用。