我正在尝试在节点结构上实现递归遍历:

sealed class Node(subnodes: Traversable[Node]) extends Traversable[Node] {
  def foreach[U](f: Node => U) {
    f(this)
    subnodes foreach f
  }
}

case class Atom(id: String) extends Node(Nil)

case class Molecule(atoms: List[Node]) extends Node(atoms)

在像toString这样的元素上调用Atom("test").toString会导致堆栈溢出:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.System.arraycopy(Native Method)
at java.lang.String.getChars(Unknown Source)
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at scala.collection.mutable.StringBuilder.append(StringBuilder.scala:197)
at scala.collection.TraversableOnce$class.addString(TraversableOnce.scala:297)
at Node.addString(Fail.scala:1)
at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:263)
at Node.mkString(Fail.scala:1)
at scala.collection.TraversableLike$class.toString(TraversableLike.scala:615)
at Node.toString(Fail.scala:1)
at java.lang.String.valueOf(Unknown Source)
at scala.collection.mutable.StringBuilder.append(StringBuilder.scala:187)
at scala.collection.TraversableOnce$$anonfun$addString$1.apply(TraversableOnce.scala:300)
[...]
at Node.foreach(Fail.scala:3)
at scala.collection.TraversableOnce$class.addString(TraversableOnce.scala:298)
at Node.addString(Fail.scala:1)
at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:263)
at Node.mkString(Fail.scala:1)
at scala.collection.TraversableLike$class.toString(TraversableLike.scala:615)
at Node.toString(Fail.scala:1)
at java.lang.String.valueOf(Unknown Source)
at scala.collection.mutable.StringBuilder.append(StringBuilder.scala:187)
at scala.collection.TraversableOnce$$anonfun$addString$1.apply(TraversableOnce.scala:300)

请注意,我没有在任何地方明确调用foreach。那么,为什么会出现堆栈溢出?

我通过额外的TraversableNode类和从NodeTraversableNode的隐式转换解决了这个特定问题,但我仍然想知道是什么导致堆栈溢出。谢谢。

最佳答案

当您在toString上调用Atom时,您将获得Traversablethe documentation描述如下:

默认情况下,此字符串包含此字符串的stringPrefix 集合,然后是所有用逗号分隔并括起来的元素
在括号内。

通过所有集合的TraversableOnce来实现in foreach ,以实现“所有元素都遵循”。由于您的foreach首先碰到了Node本身,因此您立即陷入无休止的循环。

10-06 10:37
查看更多