& str String和生命周期

时间:2015-03-11 23:20:08

标签: rust

我正在研究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()];
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我认为这样的事情应该有效,因为我只会处理受体。

1 个答案:

答案 0 :(得分:3)

(顺便说一下:foo[i..foo.len()]应始终等同于foo[i..]。)

如果self.text[i..]类型为strself.text,则String的类型为未归类型&str。为了使其大小(因此,为了使其工作),您需要将其转换为与text相同的类型。

如果textString,可以通过在切片结果上调用.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)。前者适用于迭代器(参见上述答案),而后者则不适用。