これについて
Scalaのfor文を掘ってみる
分かる範囲で補足的なもの。versionは2.9.1です
yield処理は、apply$mcII$sp()
このapplyっていうのは無名関数がコンパイルされた際に名前がつくやつですね。
flatMapの引数は無名関数なわけですから、簡単に言うと for の中の <- の数の分くらい無名関数生成されます。また無名関数は内部クラスに変換されるので、内部クラスがどんどんネストして、あんな感じの長いクラスファイル名になるわけです。
そしてこの場合の無名関数は Function1 型です。Function1 型には specialized アノテーションがついてます。specializedアノテーションが付いている場合、(Boxingが起きないように)それぞれの型に応じてメソッドが生成されます。たとえば以下のようにしてみればわかりますが
scala> {x:Int => x}.getClass.getMethods.foreach(println) public final int $line4.$read$$iw$$iw$$anonfun$1.apply(int) public final java.lang.Object $line4.$read$$iw$$iw$$anonfun$1.apply(java.lang.Object) public int $line4.$read$$iw$$iw$$anonfun$1.apply$mcII$sp(int) public scala.Function1 scala.runtime.AbstractFunction1$mcII$sp.compose(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1$mcII$sp.compose$mcII$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1$mcII$sp.andThen(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1$mcII$sp.andThen$mcII$sp(scala.Function1) public java.lang.String scala.runtime.AbstractFunction1.toString() public boolean scala.runtime.AbstractFunction1.apply$mcZD$sp(double) public double scala.runtime.AbstractFunction1.apply$mcDD$sp(double) public float scala.runtime.AbstractFunction1.apply$mcFD$sp(double) public int scala.runtime.AbstractFunction1.apply$mcID$sp(double) public long scala.runtime.AbstractFunction1.apply$mcJD$sp(double) public void scala.runtime.AbstractFunction1.apply$mcVD$sp(double) public boolean scala.runtime.AbstractFunction1.apply$mcZF$sp(float) public double scala.runtime.AbstractFunction1.apply$mcDF$sp(float) public float scala.runtime.AbstractFunction1.apply$mcFF$sp(float) public int scala.runtime.AbstractFunction1.apply$mcIF$sp(float) public long scala.runtime.AbstractFunction1.apply$mcJF$sp(float) public void scala.runtime.AbstractFunction1.apply$mcVF$sp(float) public boolean scala.runtime.AbstractFunction1.apply$mcZI$sp(int) public double scala.runtime.AbstractFunction1.apply$mcDI$sp(int) public float scala.runtime.AbstractFunction1.apply$mcFI$sp(int) public long scala.runtime.AbstractFunction1.apply$mcJI$sp(int) public void scala.runtime.AbstractFunction1.apply$mcVI$sp(int) public boolean scala.runtime.AbstractFunction1.apply$mcZJ$sp(long) public double scala.runtime.AbstractFunction1.apply$mcDJ$sp(long) public float scala.runtime.AbstractFunction1.apply$mcFJ$sp(long) public int scala.runtime.AbstractFunction1.apply$mcIJ$sp(long) public long scala.runtime.AbstractFunction1.apply$mcJJ$sp(long) public void scala.runtime.AbstractFunction1.apply$mcVJ$sp(long) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcZD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcDD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcFD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcID$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcJD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcVD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcZF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcDF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcFF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcIF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcJF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcVF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcZI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcDI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcFI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcJI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcVI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcZJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcDJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcFJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcIJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcJJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.compose$mcVJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcZD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcDD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcFD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcID$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcJD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcVD$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcZF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcDF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcFF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcIF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcJF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcVF$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcZI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcDI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcFI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcJI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcVI$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcZJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcDJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcFJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcIJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcJJ$sp(scala.Function1) public scala.Function1 scala.runtime.AbstractFunction1.andThen$mcVJ$sp(scala.Function1) public final void java.lang.Object.wait() throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public boolean java.lang.Object.equals(java.lang.Object) public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll()
いっぱいメソッドできてます。(おそらく)この mcII の II は 引数が Int で戻り値も Int という意味です。(Intの頭文字のI) そしてこの場合も、{x:Int => x}というものを定義したので
public int $line4.$read$$iw$$iw$$anonfun$1.apply$mcII$sp(int)
となっていますよね?これを
{x:Double => x}
や
{x:Long => x}
にすれば、msIIではなく、その部分が微妙に違う文字列になるはずです。その後の sp は specialized の略ですかね?ちなみに、実装がこうなっているっていうだけでこのあたりは仕様で決まってるわけではありません。べつに覚える必要ありません。そもそもversionによって変わり得ますし。
あと、stackoverflowするのはまぁJVMのスタックサイズのオプションを変えて起動すれば、それなりに変わるんじゃないかなぁーとおもいます。
それと、あまり自信ないけど適当な予想
クラス名に anonfun とか apply っていう名前が入るのは知ってたけど、これある程度内部クラスのネスト深くなった場合に、クラスファイル名が長くなりすぎないように、ハッシュ値入れてるのかな URL
2012-01-26 01:02:06 via web
以上、べつにあまり役に立たないどうでもいい話・・・(´・ω・`)