&str 字符串和生命周期
&str String and lifetime
我正在用 Rust 开发一个小型词法分析器。我想到了将词法分析阶段放入 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 错误:方法 `next` 的特征类型不兼容:预期绑定生命周期参数,找到具体生命周期 [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()];
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我认为这样的事情应该可行,因为我只处理子切片。
(顺便说一句:foo[i..foo.len()]
应始终等同于 foo[i..]
。)
如果 self.text
是 String
或 &str
类型,self.text[i..]
的类型是未调整大小的类型 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..];
.
一辈子的事,请看我对的回答;它解释了 fn next(&'a mut self)
等问题。
在我看来,您希望整个事情都基于字符串切片 (&str
) 而不是拥有的字符串 (String
)。前者适用于迭代器(参见上述答案),而后者则不行。
我正在用 Rust 开发一个小型词法分析器。我想到了将词法分析阶段放入 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 错误:方法 `next` 的特征类型不兼容:预期绑定生命周期参数,找到具体生命周期 [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()]; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我认为这样的事情应该可行,因为我只处理子切片。
(顺便说一句:foo[i..foo.len()]
应始终等同于 foo[i..]
。)
如果 self.text
是 String
或 &str
类型,self.text[i..]
的类型是未调整大小的类型 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..];
.
一辈子的事,请看我对的回答;它解释了 fn next(&'a mut self)
等问题。
在我看来,您希望整个事情都基于字符串切片 (&str
) 而不是拥有的字符串 (String
)。前者适用于迭代器(参见上述答案),而后者则不行。