I am looking into scala TCO and have written the following code
import scala.annotation.tailrec
final def tailReccursionEx(str:String):List[String]={
@tailrec
def doTailRecursionEx(str:String,pos:Int,accu:List[String]):List[String]={
if(pos==str.length) return accu
else{
doTailRecursionEx(str,pos+1,accu++accu.foldLeft(List[String](str(`pos`).toString)){
(l,ch)=>l:+ch+str(`pos`)})
}
}
doTailRecursionEx(str,0,List[String]())
}
I have passed the @tailrec test and I believe that my function is self-recursive tail call. Yet, when I look into the java byte code with
javap -c -private RecursionEx\$\$anonfun\$doTailRecursionEx\$1\$1
I don't see the promised goto for the TCO for self-recursive function. Here is the bytecode.
public RecursionEx$$anonfun$doTailRecursionEx$1$1(java.lang.String, int);
Code:
0: aload_0
1: aload_1
2: putfield #35; //Field str$2:Ljava/lang/String;
5: aload_0
6: iload_2
7: putfield #41; //Field pos$1:I
10: aload_0
11: invokespecial #93; //Method scala/runtime/AbstractFunction2."<init>":()V
14: return
}
I think you need to run javap
on a different generated class file. The file you are examining at present corresponds to the closure you use as part of foldLeft
. If you try looking at the "RecursionEx$.class" file you should see the tail call recursion. When I compile the code:
import scala.annotation.tailrec
object RecursionEx {
@tailrec
final def doTailRecursionEx(str: String, pos: Int, accu: List[String]): List[String] = {
if (pos == str.length) return accu
doTailRecursionEx(str, pos + 1 , accu ++ accu.foldLeft(List[String](str(`pos`).toString)) {
(l, ch) => l :+ ch + str(`pos`)
})
}
def main(args: Array[String]) {
doTailRecursionEx("mew",0,List[String]())
}
}
and then run javap -c -private RecursionEx$
I see the following for the relevant section of code:
public final scala.collection.immutable.List doTailRecursionEx(java.lang.String, int, scala.collection.immutable.List);
Code:
0: iload_2
1: aload_1
2: invokevirtual #21; //Method java/lang/String.length:()I
5: if_icmpne 10
8: aload_3
9: areturn
10: iload_2
11: iconst_1
12: iadd
13: aload_3
14: aload_3
15: getstatic #26; //Field scala/collection/immutable/List$.MODULE$:Lscala/collection/immutable/List$;
18: getstatic #31; //Field scala/Predef$.MODULE$:Lscala/Predef$;
21: iconst_1
22: anewarray #17; //class java/lang/String
25: dup
26: iconst_0
27: getstatic #31; //Field scala/Predef$.MODULE$:Lscala/Predef$;
30: aload_1
31: invokevirtual #35; //Method scala/Predef$.augmentString:(Ljava/lang/String;)Lscala/collection/immutable/StringOps;
34: iload_2
35: invokeinterface #41, 2; //InterfaceMethod scala/collection/immutable/StringLike.apply:(I)C
40: invokestatic #47; //Method scala/runtime/BoxesRunTime.boxToCharacter:(C)Ljava/lang/Character;
43: invokevirtual #53; //Method java/lang/Object.toString:()Ljava/lang/String;
46: aastore
47: checkcast #55; //class "[Ljava/lang/Object;"
50: invokevirtual #59; //Method scala/Predef$.wrapRefArray:([Ljava/lang/Object;)Lscala/collection/mutable/WrappedArray;
53: invokevirtual #62; //Method scala/collection/immutable/List$.apply:(Lscala/collection/Seq;)Lscala/collection/immutable/List;
56: new #64; //class RecursionEx$$anonfun$doTailRecursionEx$1
59: dup
60: aload_1
61: iload_2
62: invokespecial #67; //Method RecursionEx$$anonfun$doTailRecursionEx$1."<init>":(Ljava/lang/String;I)V
65: invokeinterface #73, 3; //InterfaceMethod scala/collection/LinearSeqOptimized.foldLeft:(Ljava/lang/Object;Lscala/Function2;)Ljava/lang/Object;
70: checkcast #75; //class scala/collection/TraversableOnce
73: getstatic #26; //Field scala/collection/immutable/List$.MODULE$:Lscala/collection/immutable/List$;
76: invokevirtual #79; //Method scala/collection/immutable/List$.canBuildFrom:()Lscala/collection/generic/CanBuildFrom;
79: invokevirtual #85; //Method scala/collection/immutable/List.$plus$plus:(Lscala/collection/TraversableOnce;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;
82: checkcast #81; //class scala/collection/immutable/List
85: astore_3
86: istore_2
87: goto 0
with a goto
at the end, just as you would expect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With