如何 return 具有来自函数的 String 类型字段的结构的 Vec?

How to return a Vec of structs that have a String type field from a function?

我正在开发一个具有函数 lex 的词法分析器,它应该将扫描标记的向量移动到一个主程序,然后主程序将生成一个解析器来解析标记,定义如下:

/// ### lex
/// Pushes the tokens generated by
/// `scan_token` to `self.tokens`
fn lex(&mut self) -> Vec<Token> {
    while !Self::is_at_eof(self) {
        self.lexeme_start = self.lookahead;
        self.tokens.push(Self::scan_token(self).unwrap());
    }
    self.tokens
        .push(Token::new(TokenType::EOF, String::from(""), self.row));
    self.tokens
}

向量 self.tokens: Vec<Token> 应包含定义为

的标记
pub struct Token {
    // -- snip of copyable fields --
    lexeme: String, // <-- the issue
    // -- snip of copyable fields --
}

但是,这不会编译,因为 String 类型没有实现 Copy 特性。在将所有权传递给函数调用者(如移动它)时,我如何 return 这个向量?

我知道这个函数不是public,所以它不能被模块外的任何东西调用,但一旦我测试成功它就会被调用。

However, this will not compile, as the String type does not implement the Copy trait. How might I return this vector while passing ownership to the function caller (as in move it)?

你……不能?这真的没有意义,为什么你们都将令牌流存储在自己身上并 returning 它?一个或另一个是有意义的(毕竟调用者可以根据需要从标记器获取标记)。或者,如果您希望能够,比如说,出于某种原因进行链式调用,您可以 return 一个 referenceSelf 所拥有的令牌流。

/// Option 0: return a reference to the Vec (could be mutable, so you could push into it)
fn lex0(&mut self) -> &Vec<Token> {
    while !self.is_at_eof() {
        self.lexeme_start = self.lookahead;
        self.scan_token();
    }
    self.tokens.push(Token::new(TokenType::EOF, String::from(""), self.row));
    &self.tokens
}
/// Option 1: return a slice reference (could be mutable, couldn't push into it)
fn lex1(&mut self) -> &[Token] {
    while !self.is_at_eof() {
        self.lexeme_start = self.lookahead;
        self.scan_token();
    }
    self.tokens.push(Token::new(TokenType::EOF, String::from(""), self.row));
    &self.tokens
}

或者,按值获取 self 以便使用它,这样您就可以在销毁后者时 令牌从 self 中移出.

/// Option 2: consume lexer and return tokens stream
fn lex2(mut self) -> Vec<Token> {
    while !self.is_at_eof() {
        self.lexeme_start = self.lookahead;
        self.scan_token();
    }
    self.tokens.push(Token::new(TokenType::EOF, String::from(""), self.row));
    self.tokens
}

最后,您可以在 Token 上实现 Clone,并将整个 Vec 克隆到 return,但这似乎效率不高。

#[derive(Clone)]
struct Token {...}

/// Option 3: copy tokens stream
fn lex3(&mut self) -> Vec<Token> {
    while !self.is_at_eof() {
        self.lexeme_start = self.lookahead;
        self.scan_token();
    }
    self.tokens.push(Token::new(TokenType::EOF, String::from(""), self.row));
    self.tokens.clone()
}

不真正了解潜在需求是什么,很难提供好的建议。