2011-11-21 27 views
5

Tôi nhìn vào scala TCO và đã viết đoạn mã sauđang scala của tôi không có được TCO'ed mặc dù nó đi @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]()) 
} 

tôi đã vượt qua bài kiểm tra @tailrec và tôi tin rằng chức năng của tôi là cuộc gọi đuôi tự đệ quy. Tuy nhiên, khi tôi nhìn vào mã byte java với

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

Tôi không thấy hứa goto cho TCO cho chức năng tự đệ quy. Đây là 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 

} 

Trả lời

10

Tôi nghĩ rằng bạn cần phải chạy javap trên một tập tin lớp được tạo ra khác nhau. Tệp bạn đang kiểm tra hiện tại tương ứng với phần đóng mà bạn sử dụng như một phần của foldLeft. Nếu bạn thử xem tập tin "RecursionEx $ .class", bạn sẽ thấy đệ quy cuộc gọi đuôi. Khi tôi biên dịch mã:

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

và sau đó chạy javap -c -private RecursionEx$ tôi thấy những điều sau đây cho các phần có liên quan của mã:

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 

với một goto ở cuối, cũng giống như bạn mong đợi.

Các vấn đề liên quan