加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

我的scala代码虽然通过@tailrec但没有得到TCO

发布时间:2020-12-16 18:40:21 所属栏目:安全 来源:网络整理
导读:我正在研究 scala TCO并编写了以下代码 import scala.annotation.tailrecfinal def tailReccursionEx(str:String):List[String]={ @tailrec def doTailRecursionEx(str:String,pos:Int,accu:List[String]):List[String]={ if(pos==str.length) return accu e
我正在研究 scala TCO并编写了以下代码

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,List[String]())
}

我已通过@tailrec测试,我相信我的函数是自递归尾调用.然而,当我查看java字节代码时

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

我没有看到TCO承诺的自我递归功能.这是字节码.

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

}

解决方法

我认为你需要在不同的生成类文件上运行javap.您当前检查的文件对应于您作为foldLeft的一部分使用的闭包.如果您尝试查看“RecursionEx $.class”文件,您应该看到尾调用递归.当我编译代码时:

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",List[String]())
    }
}

然后运行javap -c -private RecursionEx $我看到以下代码的相关部分:

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

正如你所期望的那样,最后有一个goto.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读