2009-04-15 54 views
109

Scala中的模式匹配如何在字节码级别上实现?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) 
} 

P.S.我可以读取Java字节码,因此字节码表示对我来说足够好,但是对其他读者来说,它可能更好地知道它将如何看起来像Java代码。

P.P.S.本书Programming in Scala是否回答了有关Scala如何实施的类似问题?我已经订购了这本书,但还没有到。

+0

你为什么不只是编译的例子,用Java字节码反汇编拆开呢? – Zifre 2009-04-15 23:36:39

+0

我可能会这样做,除非有人先给出一个好的答案。但现在我想睡一觉。 ;) – 2009-04-15 23:41:44

回答

85

水平低可以用反汇编探讨,但简单的答案是,它是一堆如果/别人的地方谓词依赖于模式

case Sum(l,r) // instance of check followed by fetching the two arguments and assigning to two variables l and r but see below about custom extractors 
case "hello" // equality check 
case _ : Foo // instance of check 
case x => // assignment to a fresh variable 
case _ => // do nothing, this is the tail else on the if/else 

还有更多,您可以用喜欢的图案做或者像“case Foo(45,x)”这样的模式和组合,但通常这些只是我刚才描述的逻辑扩展。模式也可以有警卫,这是对谓词的附加限制。还有一些情况是编译器可以优化模式匹配,例如,当它们可能合并一些事例的情况之间存在某种重叠时。高级模式和优化是编译器中一个活跃的工作领域,所以如果字节码在当前和未来版本的Scala中基本改进了这些基本规则,不要感到惊讶。

除了这一切,你可以写,除了自己的自定义提取或替代默认的斯卡拉使用的情况下类。如果你这样做,那么模式匹配的成本就是提取器的成本。一个很好的概述中http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf

70

詹姆斯发现(上图)说得好。但是,如果你很好奇,查看反汇编的字节码总是一个很好的练习。您也可以调用scalac-print选项,这将删除所有的Scala的特定功能打印程序。它基本上是Scala服装中的Java。下面是有关scalac -print输出你给的代码片段:

def eval(e: Expr): Int = { 
    <synthetic> val temp10: Expr = e; 
    if (temp10.$isInstanceOf[Number]()) 
    temp10.$asInstanceOf[Number]().n() 
    else 
    if (temp10.$isInstanceOf[Sum]()) 
     { 
     <synthetic> val temp13: Sum = temp10.$asInstanceOf[Sum](); 
     Main.this.eval(temp13.e1()).+(Main.this.eval(temp13.e2())) 
     } 
    else 
     throw new MatchError(temp10) 
};