我正在为Rust编写一个小型的词法分析器。我想把词法分析阶段放到Iterator
trait的实现中。
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: 方法 `next` 的 trait 类型不兼容: 预期绑定生命周期参数,发现具体的生命周期 [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 错误: 类型不匹配: 期望 `&'a str`, 找到 `str` (期望 &-ptr, 找到 str) [E0308] src/lexer.rs:66 self.text = self.text[i .. self.text.len()]; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我认为这样的代码应该是可以工作的,因为我只使用子切片。
to_string()
/to_owned()
中哪一个更符合惯用法? - julen.to_string()
使用相对较重的std::fmt
基础设施。在像字符串这样的简单情况下,它现在应该会在运行时完全优化掉(当我写答案时这不是完全正确的),但是有一些轻微的变体你可以形成,它们无法完美地优化掉,并且仍然存在一些编译时开销。我自己现在可能最常写String::from(text)
,但是我也不会对text.to_string()
感到惊讶。 - Chris Morgan