2

下面是我的代码片段:

sealed abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr

object CaseClassTest extends App {
    def simplifyExp(xs: Expr): Expr = xs match {
      case UnOp("-",UnOp("-", x)) => x
      case BinOp("+",x,Number(0)) => x
      case BinOp("*",x,Number(1)) => x
    }

    def describe(e: Expr): String = e match {
      case Number(_) => "Number"
      case Var(_) => "Var"
    } 
}

现在在 describe 方法中发生了什么,我收到一条警告,指出“匹配可能并不详尽。它会在以下输入上失败:BinOp(_, _, ), UnOp( , _) ”。它对我来说看起来很完美,因为我没有考虑 BinOp、UnOp 等其他测试用例。完美的

但是我的问题是为什么def simpleExp(xs: Expr): Expr没有出现同样的警告?有什么我想念的吗?谢谢

4

2 回答 2

5

在这种情况下simplifyExp,您使用提取器组合,我认为编译器不够聪明,无法检测到问题。

显然,以下代码在运行时失败MatchError

CaseClassTest.simplifyExp(Var("toto"))
于 2013-11-08T18:38:16.343 回答
0

编译器显示一个真正的警告,因为simplifyExp无法处理 type 的所有参数Expr。例如在做:

scala> simplifyExp(new Var("as"))
scala.MatchError: Var(as) (of class Var)
        at .simplifyExp(<console>:22)
        at .<init>(<console>:24)...

同样,它不能处理类型的参数,BinOp(_, _, _)即 BinOp 采用任何 String、任何左 Expr、右 Expr。

关于第二个函数,更改声明的顺序,它describe还会显示警告:

scala> object CaseClassTest extends App {
    def describe(e: Expr): String = e match {
      case Number(_) => "Number"
      case Var(_) => "Var"
    }

    def simplifyExp(xs: Expr): Expr = xs match {
      case UnOp("-",UnOp("-", x)) => x
      case BinOp("+",x,Number(0)) => x
      case BinOp("*",x,Number(1)) => x
    }

}
<console>:23: warning: match may not be exhaustive.
It would fail on the following inputs: BinOp(_, _, _), UnOp(_, _)
           def describe(e: Expr): String = e match {
                                           ^
defined module CaseClassTest

如果您describe在上述情况下更正,那么它也会显示simplifyExpr

于 2013-11-08T18:38:54.663 回答