В этом коде я пытаюсь взять объединение двух деревьев следующим образом:

class NonEmpty(elem: Tweet, left: TweetSet, right: TweetSet) extends TweetSet {

    def union(that: TweetSet): TweetSet =
    {
      def unionRec(set:TweetSet,acc:TweetSet): TweetSet =
      {
        if (set.isEmpty)
          return acc
        else
          return unionRec(right,unionRec(left,acc.incl(elem)))
      }
      unionRec(this,that)
    }

    def isEmpty: Boolean = false

    def incl(x: Tweet): TweetSet = {
      if (x.text < elem.text) new NonEmpty(elem, left.incl(x), right)
      else if (elem.text < x.text) new NonEmpty(elem, left, right.incl(x))
      else this
    }

}

class Empty extends TweetSet {
  def isEmpty: Boolean = true
}

Но когда я пытаюсь выполнить метод union, я получаю ошибку stackOverflow:

java.lang.StackOverflowError
    at scala.collection.immutable.StringLike$class.compare(StringLike.scala:74)
    at scala.collection.immutable.StringOps.compare(StringOps.scala:30)
    at scala.collection.immutable.StringOps.compare(StringOps.scala:30)
    at scala.math.Ordered$class.$less(Ordered.scala:76)
    at scala.collection.immutable.StringOps.$less(StringOps.scala:30)
    at objsets.NonEmpty.incl(TweetSet.scala:235)
    at objsets.NonEmpty.incl(TweetSet.scala:236)
    at objsets.NonEmpty.incl(TweetSet.scala:235)
    at objsets.NonEmpty.incl(TweetSet.scala:236)
    at objsets.NonEmpty.incl(TweetSet.scala:235)
    at objsets.NonEmpty.incl(TweetSet.scala:235)
    at objsets.NonEmpty.incl(TweetSet.scala:236)
    at objsets.NonEmpty.incl(TweetSet.scala:236)
    at objsets.NonEmpty.incl(TweetSet.scala:235)

Почему это происходит?

0
sarthak 25 Ноя 2016 в 16:22

2 ответа

Лучший ответ

Чтобы рекурсия в конечном итоге завершилась, вам необходимо убедиться, что дерево в первом аргументе unionRec рано или поздно будет пустым. Поскольку вы всегда вызываете его слева и справа, ваша рекурсия никогда не завершается.

1
Buhb 25 Ноя 2016 в 17:33

У вас есть метод unionRec, который является рекурсивным. Очевидно, он вызывает себя слишком много раз, что на самом деле приводит к переполнению стека.

Чтобы исправить это, вы должны переписать его, чтобы сделать хвостовую рекурсию. Scala представляет такую рекурсию как простой цикл.

Добавьте в свой метод аннотацию @tailrec, чтобы убедиться, что он удовлетворяет требованиям хвостовой рекурсии.

-2
vvg 25 Ноя 2016 в 13:28