web-dev-qa-db-ja.com

Scala=のパターンマッチングはバイトコードレベルでどのように実装されていますか?

Scala=のパターンマッチングはバイトコードレベルでどのように実装されていますか?

それは一連のif (x instanceof Foo)構文のようなものですか、それとも何か他のものですか?そのパフォーマンスへの影響は何ですか?

たとえば、次のコード( Scala By Example 46〜48ページから)を指定すると、同等のJava evalメソッドのコードはどのようになりますか?お気に入り?

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.この本 Scalaでのプログラミング は、Scalaの実装方法)に関するこれと同様の質問への回答を提供していますか?本を注文しましたが、まだ到着していません。

121
Esko Luontola

低レベルは逆アセンブラで探索できますが、簡単な答えは、述語がパターンに依存するif/elsesの集まりであるということです

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の現在および将来のバージョンのこれらの基本的なルールを大幅に改善しても驚かないでください。

これらすべてに加えて、デフォルトのエクストラに加えて、またはデフォルトのエクストラクタの代わりに、独自のカスタムエクストラクタを作成できますScalaはケースクラスに使用します。使用する場合、パターンマッチのコストはエクストラクタが実行するすべてのコスト。概要は http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf にあります。

94
James Iry

ジェームズ(上)が最もよく言った。ただし、興味がある場合は、逆アセンブルされたバイトコードを確認することをお勧めします。 -printオプションを使用してscalacを呼び出すこともできます。これにより、Scala固有の機能がすべて削除されたプログラムが印刷されます。それは基本的にJava Scalaの服を着たものです。あなたが与えたコードスニペットに関連する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)
};
76
Jorge Ortiz

バージョン2.8以降、Scalaには @ switch アノテーションが付いています。目標は、パターンマッチングが tableswitchまたはlookupswitch にコンパイルされることを確認することです。 =一連の条件付きifステートメントの代わりに。

32
om-nom-nom