8

なぜこの Scala コードは:

class Test
{
  def foo: (Int, String) =
  {
    (123, "123")
  }

  def bar: Unit =
  {
    val (i, s) = foo
  }
}

bar()new を構築し、 fromをそれTuple2に渡し、そこから値を取得するための次のバイトコードを生成しますか?Tuple2foo()

public void bar();
Code:
 0:   aload_0
 1:   invokevirtual   #28; //Method foo:()Lscala/Tuple2;
 4:   astore_2
 5:   aload_2
 6:   ifnull  40
 9:   new     #7; //class scala/Tuple2
 12:  dup
 13:  aload_2
 14:  invokevirtual   #32; //Method scala/Tuple2._1:()Ljava/lang/Object;
 17:  aload_2
 18:  invokevirtual   #35; //Method scala/Tuple2._2:()Ljava/lang/Object;
 21:  invokespecial   #20; //Method scala/Tuple2."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
 24:  astore_1
 25:  aload_1
 26:  invokevirtual   #39; //Method scala/Tuple2._1$mcI$sp:()I
 29:  istore_3
 30:  aload_1
 31:  invokevirtual   #35; //Method scala/Tuple2._2:()Ljava/lang/Object;
 34:  checkcast       #41; //class java/lang/String
 37:  astore  4

foo()これは、戻り値がタプルでないことをコンパイラがチェックしていないためですか?

とにかく、JVM は構築を最適化しますか?

4

2 に答える 2

4

これは仕様によると思われます( 4.1 値の宣言と定義- スタックオーバーフロー表示用にわずかに再フォーマットされています):

値の定義は、代わりに左側としてパターン (§8.1) を持つことができます。p が単純な名前または名前の後にコロンと型が続くパターン以外のパターンである場合、値の定義val p = eは次のように展開されます。

  1. パターンpに変数がバインドされている場合x1, . . . , xn、ここでn >= 1: ここで$xは、新しい名前です。
  val $x = e match {case p => (x1, . . . , xn)}
  val x1 = $x._1
  . . .
  val xn = $x._n

したがって、タプルの作成はパーサー フェーズで行われます。そのval (i, s) = (1, "s")ため、パーサー フェーズの最後に次のように費やされます。

private[this] val x$1 = scala.Tuple2(1, "s"): @scala.unchecked match {    
  case scala.Tuple2((i @ _), (s @ _)) => scala.Tuple2(i, s)
};
val i = x$1._1;
val s = x$1._2

100 万回の反復で、この簡単なテストでこれを測定します。

def foo: (Int, String) = (123, "123")
def bar: Unit = { val (i, s) = foo }
def bam: Unit = { val f = foo; val i = f._1; val s = f._2 }

収量

foo: Elapsed: 0.030
bar: Elapsed: 0.051
._1 ._2 access: Elapsed: 0.040

-optimize フラグを使用:

foo: Elapsed: 0.027
bar: Elapsed: 0.049
._1 ._2 access: Elapsed: 0.029
于 2011-11-19T17:05:41.333 に答える
4

scalac で最適化の機会を逃したようです。

コンパイラの関連部分はUnapplies#caseClassUnapplyReturnValueを使用します。これはTreeDSL#SOME、コードを生成して新しいTupleN

于 2011-11-19T08:14:38.850 に答える