【问题标题】:Matching against multiple Boxed values匹配多个 Boxed 值
【发布时间】:2022-08-22 00:36:29
【问题描述】:

我有以下编译好的代码

#[derive(Debug, PartialEq, Clone)]
pub enum Expression {
    Const(i32),
    Neg(Box<Expression>),
    Add(Box<Expression>, Box<Expression>),
}

fn simplify(expr: &Expression) -> Expression {
    match expr {
        Expression::Neg(x) => match **x {
            Expression::Const(n) => Expression::Const(-n),
            _ => expr.clone() 
        },  

        // GIVES ERROR
        // Expression::Add(x, y) => match (**x, **y) {
        //     (Expression::Const(n), Expression::Const(m)) => Expression::Const(n + m),
        //     _ => expr.clone() 
        // },
    
    
        Expression::Add(x, y) => match **x {
            Expression::Const(n) => match **y {
                Expression::Const(m) => Expression::Const(n + m), 
                _ => expr.clone() 
            }   
            _ => expr.clone() 
        }   


        _ => expr.clone() 
    }   
}

但是,如果我用注释掉的版本替换 Expression::Add 手臂,我会收到以下编译器错误

error[E0507]: cannot move out of `**x` which is behind a shared reference
  --> src/lib.rs:21:41
   |
21 |         Expression::Add(x, y) => match (**x, **y) {
   |                                         ^^^ move occurs because `**x` has type `Expression`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `**y` which is behind a shared reference
  --> src/lib.rs:21:46
   |
21 |         Expression::Add(x, y) => match (**x, **y) {
   |                                              ^^^ move occurs because `**y` has type `Expression`, which does not implement the `Copy` trait

For more information about this error, try `rustc --explain E0507`.

我们是否有理由匹配单独的**x,而不是像(**x, **y) 这样的元组?前者实际上是被转换还是隐藏了一些语法糖?有没有比使用两个嵌套匹配更简单的方法来编写这个Add arm?

编辑:我还看到有一个ref 关键字,即supposed to address 类似这样的东西,但是将我的元组匹配表达式更改为(ref **x, ref **y) 会产生语法错误(error: expected expression, found keyword ref)。

  • 我不确定发生了什么,但match (&amp;**x, &amp;**y) 有效。 (而ref 继续在匹配臂中进行变量声明。从语法上讲,您在错误的地方使用它。)

标签: rust match move-semantics


【解决方案1】:

TL;博士:匹配(&amp;**x, &amp;**y)


这里发生的事情很有趣。 TL;DR 是:当您match v {} 时,您不会阅读v。你创建一个地方v

一个地方是我们可以从中读取的东西。或写信给。或者什么都不做。重要的一点是,单独创造场所并不涉及这样的操作。您可以稍后读/写它,但是当您创建它时,它只是一个地方。

在您的match 中,xy 的类型为&amp;Box&lt;Expression&gt;。当我们match **x我们不读x.因此,我们也不会移动**x。我们所做的是为**x 创建一个位置。然后我们将这个地方与Expression::Const(n) 进行匹配。现在我们读取x 并从中提取n。但是ni32 - Copy - 所以这很好。

相反,当您使用元组(**x, **y) 时,由于您不直接匹配**x**y,因此您确实会读取它们。因为你读过它们,它们不是Copy (Expression),所以你离开了它们。现在这是一个错误,因为您无法移出共享参考。你匹配他们,但他们已经搬家了。

【讨论】:

    【解决方案2】:

    你可以试试match(x.as_ref(),y.as_ref())

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-20
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多