有没有一种简洁的方法来匹配深度嵌套的盒子?

huangapple go评论65阅读模式
英文:

Is there a concise way to match deeply nested boxes?

问题

以下是您要翻译的代码部分:

match node {
    ConstantExpression::ConstantPrimary(Box(ConstantPrimary::PrimaryLiteral(Box(
        PrimaryLiteral::Number(Box(Number::IntegralNumber(Box(
            IntegralNumber::DecimalNumber(Box(DecimalNumber::UnsignedNumber(unsigned_number))),
        )))),
    )))) => Some(unsigned_number),
    _ => None,
};

希望这有所帮助。如果您需要任何其他翻译,请随时提出。

英文:

There are a number of questions on this site about pattern matching Box<>, and it currently can't be done on stable Rust (one, two, three etc.). But those questions are all about single levels of box. I have a deeply nested Box/Enum tree. Basically I want to do this:

match node {
    ConstantExpression::ConstantPrimary(Box(ConstantPrimary::PrimaryLiteral(Box(
        PrimaryLiteral::Number(Box(Number::IntegralNumber(Box(
            IntegralNumber::DecimalNumber(Box(DecimalNumber::UnsignedNumber(unsigned_number))),
        )))),
    )))) => Some(unsigned_number),
    _ => None,
};

Is there a way to do this on stable Rust that isn't extremely verbose?

(Edit: This is not a duplicate of this question; I already know you can't do it using match. I was asking for an alternative way to do it.)

答案1

得分: 2

以下是翻译好的部分:

问题与匹配框之外,并没有多余的信息在你的模式中。你必须至少提到每个枚举变体一次来指定你想要的内容。要使模式不那么笨重,你可以逐级处理:

pub fn extract_unsigned_number(node: ConstantExpression) -> Option<UnsignedNumber> {
    let ConstantExpression::ConstantPrimary(constant_primary) = node else { return None };
    let ConstantPrimary::PrimaryLiteral(primary_literal) = *constant_primary else { return None };
    let PrimaryLiteral::Number(number) = *primary_literal else { return None };
    let Number::IntegralNumber(integral_number) = *number else { return None };
    let IntegralNumber::DecimalNumber(decimal_number) = *integral_number else { return None };
    let DecimalNumber::UnsignedNumber(unsigned_number) = *decimal_number else { return None };
    Some(*unsigned_number)
}

你可以使用声明性宏稍微减少重复,但代码会变得更加晦涩,所以我个人建议就使用现在的代码。

英文:

The problem of matching against boxes aside, there isn't really any redundant information in your pattern. You have to mention each enum variant at least once to specify what you want. The best you can do to make the pattern less unwieldy is doing one level at a time:

pub fn extract_unsigned_number(node: ConstantExpression) -&gt; Option&lt;UnsignedNumber&gt; {
    let ConstantExpression::ConstantPrimary(constant_primary) = node else { return None };
    let ConstantPrimary::PrimaryLiteral(primary_literal) = *constant_primary else { return None };
    let PrimaryLiteral::Number(number) = *primary_literal else { return None };
    let Number::IntegralNumber(integral_number) = *number else { return None };
    let IntegralNumber::DecimalNumber(decimal_number) = *integral_number else { return None };
    let DecimalNumber::UnsignedNumber(unsigned_number) = *decimal_number else { return None };
    Some(*unsigned_number)
}

You could make this slightly less repetitive with a declarative macro, but the code will become more obscure, so I'd personally just use this code as it is.

huangapple
  • 本文由 发表于 2023年4月19日 17:38:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76052979.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定