递归案例类:java.lang.StackOverflowError等于

时间:2019-01-16 16:33:30

标签: scala tail-recursion

我正在使用 Scala中的功能编程进行练习,并实现了一个简单的单链接列表。

这是相关的实现部分:

sealed trait List[+T]

case class Cons[+T](t: T, ts: List[T]) extends List[T]
case object Empty extends List[Nothing]

我建立了一个“很大”列表(隐藏的目标是实现尾递归foldRight):

def mkBigListOfInt(start: Int, end: Int) = (start to end).foldRight(workshop.List[Int]()) {
  case (item, acc) => Cons(item, acc)
}

val veryBigList = mkBigListOfInt(1, 1000000)

当我尝试将列表与另一个列表进行比较时(例如使用Scalatest DSL),就会出现问题:

mkBigListOfInt(1, 1000000) shouldBe mkBigListOfInt(1, 1000000)

我得到:

[error] java.lang.StackOverflowError
[error]     at scala.runtime.BoxesRunTime.equals(BoxesRunTime.java:123)
[error]     at workshop.Cons.equals(list.scala:81)
[error]     at workshop.Cons.equals(list.scala:81)
...

(第81行是我定义的Cons案例类的行)

实现Cons以允许比较相等的好方法是什么?

由于这是一种练习,因此我可以使其简单且不完整(前提是要权衡利弊),因此“基本”解决方案目前是可以的。

1 个答案:

答案 0 :(得分:2)

案例类equals的默认实现是幼稚的递归。您可以在List中实现自己的尾部递归版本。这是一个开始:

sealed trait List[+T] {
  override def equals(o: Object): boolean = o match {
    case ls: List[_] => equalsRec(ls)
    case _ => false
  }

  @tailrec
  def equalsRec(ls: List[_]): boolean = ???