2011-11-21 6 views
5

Estoy buscando en Scala TCO y he escrito el siguiente códigoMi código Scala no recibe TCO'ed aunque pasa @tailrec

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]()) 
} 

que han pasado la prueba @tailrec y creo que mi función es llamada de cola auto recursiva. Sin embargo, cuando miro en el código de bytes de Java con

javap -c -private RecursionEx\$\$anonfun\$doTailRecursionEx\$1\$1 

no veo la prometida Goto para el coste total de propiedad para la función de auto-recursivo. Aquí está el 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 

} 

Respuesta

10

creo que necesita para ejecutar javap en un archivo de clase generada diferente. El archivo que está examinando actualmente corresponde al cierre que usa como parte de foldLeft. Si intenta mirar el archivo "RecursionEx $ .class", debería ver la repetición de la llamada final. Cuando puedo compilar el código:

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]()) 
    } 
} 

y luego ejecutar javap -c -private RecursionEx$ veo lo siguiente para la sección correspondiente del código:

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 

con un goto al final, tal y como era de esperar.

Cuestiones relacionadas