如何在字节码级别实现Scala中的模式匹配?
它是否像一系列 if (x instanceof Foo)
构造,或其他什么?它的性能影响是什么?
例如,给定以下代码(来自Scala By Example第46-48页), eval
方法的等效Java代码如何?
abstract class Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
def eval(e: Expr): Int = e match {
case Number(x) => x
case Sum(l, r) => eval(l) + eval(r)
}
附:我可以读取Java字节码,因此字节码表示对我来说已经足够好了,但是对于其他读者来说,知道它看起来像Java代码会更好 .
P.P.S.书Programming in Scala是否给出了关于Scala如何实现的类似问题的答案?我订购了这本书,但尚未到货 .
3 回答
从版本2.8开始,Scala已经有了@switch注释 . 目标是确保将模式匹配编译为tableswitch or lookupswitch而不是一系列条件
if
语句 .可以用反汇编程序探索低级别,但简短的回答是它是一堆if / elses,其中谓词依赖于模式
您可以使用“case Foo(45,x)”这样的模式或模式和组合做更多的事情,但通常这些只是我刚才描述的逻辑扩展 . 模式也可以有警戒,这是对谓词的附加约束 . 在某些情况下,编译器可以优化模式匹配,例如,当案例之间存在一些重叠时,它可能会稍微合并一些事情 . 高级模式和优化是编译器中活跃的工作领域,因此如果字节代码在当前和未来版本的Scala中大大超过这些基本规则,请不要感到惊讶 .
除此之外,除了Scala用于案例类的默认提取器之外,您还可以编写自己的自定义提取器 . 如果这样做,那么模式匹配的成本就是提取器所做的任何成本 . http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf中有一个很好的概述
詹姆斯(上图)说得最好 . 但是,如果你查看反汇编的字节码总是很好的练习're curious it' . 您还可以使用
-print
选项调用scalac
,该选项将打印您的程序,并删除所有Scala特定的功能 . 它's basically Java in Scala'的服装 . 以下是您提供的代码段的相关scalac -print
输出: