Scala在匹配模式时,按照模式定义的顺序依次检查,因此越特定的规则越要先定义,而通用的规则后定义。比如我们修改之前的
def simplifyTop(expr :Expr) :Expr = expr match {
case UnOp("-",UnOp("-",e))=>e
case BinOp("+",e,Number(0))=>e
case BinOp("*",e,Number(1))=>e
case _ => expr
}
使它可以简化任意层次的表达式,我们需要添加两个通用的规则,定义如下:
def simplifyAll(expr :Expr) :Expr = expr match {
case UnOp("-",UnOp("-",e))=>e
case BinOp("+",e,Number(0))=>e
case BinOp("*",e,Number(1))=>e
case UnOp(op,e) => UnOp(op,simplifyAll(e))
case BinOp(op,l,r)=>BinOp(op,simplifyAll(l),simplifyAll(r))
case _ => expr
}
simplifyAll规则1是规则4的特例,而规则2,3是规则5的特例,因此1,2,3需要定义在4,5之前,而最后的缺省规则需要放在最后,如果顺序反了,比如把通用的规则放在特例之前,编译器会给出警告,因为当Scala做匹配时,按照规则定义的顺序,首先匹配通用规则,规则匹配成功,后面的特例没有机会匹配,比如:
def simplifyBad(expr:Expr):Expr = expr match{
case UnOp(op,e) => UnOp(op,simplifyBad(e))
case UnOp("-",UnOp("-",e))=>e
}
<console>:12: warning: unreachable code
case UnOp("-",UnOp("-",e))=>e
^
simplifyBad: (expr: Expr)Expr