【问题标题】:Matching on an Option static string literal in Rust [duplicate]匹配 Rust 中的 Option 静态字符串文字 [重复]
【发布时间】:2018-03-03 14:31:42
【问题描述】:

编辑:事实证明,Rust 编译器不够聪明,无法传递有关变量是否是静态定义的信息。在您进行模式匹配时,编译器只知道它是一个字符串。

我正在尝试在 Rust 中创建一个解析器,并且我已经定义了一个 Token 枚举。

pub enum Constant {
    String(String),
}

pub enum Token {
    KwIf,
    KwThen,
    KwElse,
    Constant(Constant),
}

我还写了一个literal函数,重要的是这个函数返回静态字符串(即&'static str),由于性能原因(字符串也永远不会改变,所以它们保持不变是有意义的整个程序的生命周期)。

impl Token {
    pub fn literal(&self) ->  Option<&'static str> {
        match self {
            &Token::KwIf => Some("if"),
            &Token::KwThen => Some("then"),
            &Token::KwElse => Some("else"),
            _ => None,
        }
    }
}

我现在遇到的问题是,你将如何与 literal 函数进行模式匹配并使用 rust print! 函数直接打印文字字符串,即假设我写了这样的内容

use Constant::*;
pub fn print_token(token: Token) {
    match token.literal() {
        Some(literal) => print!(literal);
        None => match token {
            Token::Constant(constant) => match constant {
                String(string) => print!("{}", string),
                _ => panic!("Unexpected token"),
            }
        }
    }
}

问题是当我尝试打印此文字时出现编译错误,即我得到的编译错误是error: format argument must be a string literal. 我已经尝试了许多如何打印静态字符串文字的组合,而无需将其转换为正常的String(这当然违背了首先使用静态字符串文字的目的)。

或者,是否有更好的方法来解决我要解决的问题,我正在为一种语言制作解析器,并且很快,我正在编写令牌以及解析器/打印机。

【问题讨论】:

    标签: string enums static rust optional


    【解决方案1】:

    我认为问题出在这一行

    Some(literal) => print!(literal);
    

    应该是

    Some(literal) => print!("{}", literal),
    

    与您在 None 情况下所做的相同。

    我相信println!使用格式!宏和根据 rust 文档

    “第一个参数格式!接收的是格式字符串。这必须是字符串文字。”

    https://doc.rust-lang.org/std/macro.format.html

    【讨论】:

    • 我知道你可以做Some(literal) =&gt; print!("{}", literal),,问题是literal 值是一个字符串静态文字,因此print!(literal) 应该可以工作。除非我弄错了,否则如果您使用 print!("{}",literal),这首先会破坏使用字符串静态文字的意义,因为它的性能会最差(因为您要将字符串静态文字转换为普通字符串)。需要明确的是,如果你不使用 Option 代码可以正常工作,print!(literal) 将可以工作,因为编译器可以推断出它的静态字符串文字。
    • 你确定这有效吗?我试过let f = "Hello"; println!(f); 并得到'错误:预期文字'。据我所知,文字是源代码中出现的实际值。在 match 语句中,您创建了一个名为 literal 的新绑定,但它实际上不是文字值,因此会出现错误。
    • 感谢链接,我意识到 Rust 编译器不够聪明,无法确定它仍然是静态文字字符串。 rust 编译器确实会在 AST 中传递类型信息,但不会传递变量是否被静态定义为文字。
    • @mdedetrich print! 的格式参数实际上是代码(一种特定于域的语言),而不是数据。 print! 宏根据其值生成不同的代码,即它是将 DSL 转换为 rust 的编译器。所以print!的每个宏扩展必须只有一个可能的DSL程序。
    猜你喜欢
    • 2019-12-26
    • 2014-11-21
    • 2015-03-08
    • 1970-01-01
    • 2016-11-05
    • 2020-06-14
    • 1970-01-01
    • 2019-09-22
    • 2018-01-06
    相关资源
    最近更新 更多