如何从函数中返回一个具有String类型字段的结构的Vec?

问题描述 投票:0回答:1

我正在做一个词典,其中有一个函数是 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 特质。我怎样才能在将所有权传递给函数调用者的同时返回这个向量(比如移动它)?

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

rust return-value move-semantics return-type
1个回答
3
投票

然而,这将无法编译,因为String类型没有实现Copy特征。我怎样才能在将所有权传递给函数调用者的同时返回这个向量(比如移动它)?

你...不能?这真的没有意义,为什么你既要把token流存储在self上,又要返回它?其中之一是有意义的(毕竟如果调用者想的话,可以直接从tokenizer中获取token)。或者,如果你想要的能力,比如说,出于某种原因,你可以返回一个 参考 所拥有的令牌流。Self 是。

/// 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
}

最后,你可以实现 Clone 关于 Token 并克隆整个Vec来返回,但这样似乎效率很低。

#[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()
}

由于不知道底层需求是什么,很难提供好的建议。

© www.soinside.com 2019 - 2024. All rights reserved.