scala – @tailrec错误“递归调用目标超类型”
发布时间:2020-12-16 09:52:59 所属栏目:安全 来源:网络整理
导读:应用@tailrec我从 scala编译器得到错误:“无法优化@tailrec带注释的方法get:它包含一个针对超类型case _ = tail.get(n-1)”的递归调用.有人可以解释为什么会这样吗? trait List[T] { def isEmpty: Boolean def head: T def tail: List[T] def get(n: Int)
应用@tailrec我从
scala编译器得到错误:“无法优化@tailrec带注释的方法get:它包含一个针对超类型case _ => tail.get(n-1)”的递归调用.有人可以解释为什么会这样吗?
trait List[T] { def isEmpty: Boolean def head: T def tail: List[T] def get(n: Int): T } class Cons[T](val head: T,val tail: List[T]) extends List[T]{ def isEmpty = false @tailrec final def get(n: Int) = n match { case 0 => head case _ => tail.get(n-1) } } class Nil[T] extends List[T]{ def isEmpty = true def head = throw new NoSuchElementException("Nil.head") def tail = throw new NoSuchElementException("Nil.tail") final def get(n: Int): T = throw new IndexOutOfBoundsException } object Main extends App{ println(new Cons(4,new Cons(7,new Cons(13,new Nil))).get(3)) } 解决方法
试着想象一下这里发生了什么,以及你要求编译器做什么.粗略的尾部调用优化将方法调用转换为循环,获取方法的参数并将它们转换为在循环的每次迭代中重新分配的变量.
这里有两个这样的“循环变量”:n和调用get方法的列表单元本身,实际上是在方法体中. n的下一个值很好:它是n – 1,也是Int.列表单元格的下一个值(尾部)是一个问题,但是:它具有类型Cons [T],但尾部只有类型List [T]. 因此,编译器无法将其转换为循环,因为无法保证tail是一个Cons [T] – 当然,在列表的末尾,它是一个Nil. “修复”它的一种方法是: case class Cons[T](val head: T,val tail: List[T]) extends List[T] { def isEmpty = false @tailrec final def get(n: Int) = n match { case 0 => head case _ => tail match { case c @ Cons(_,_) => c.get(n - 1) case nil @ Nil() => nil.get(n - 1) } } } (如果Cons和Nil都是案例类,则可以工作 – 但是您可能希望在T中使Nil成为案例对象和List [T]协变量.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- angularjs – 量角器如何首先运行登录测试脚本
- angularjs – Angular&Ionic,HTTP在实际的设备IOS中无法
- angularjs – Angular Control在缩小JS文件后无法正常工作?
- scala – 使用spark-csv重载方法错误
- ServiceStack 项目实例 001 建立项目结构
- GlassFish 中的 命令框架 (CLI) 实现
- scala – 一个非托管jar文件中的SBT插件
- BootStrap Table实现server分页序号连续显示功能(当前页从
- bootstrap 模态框(modal)实现水平垂直居中显示
- 使用 MEAN 进行全栈开发基础篇——6、接着前面玩儿删除