我正在尝试在节点结构上实现递归遍历:
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
类和从Node
到TraversableNode
的隐式转换解决了这个特定问题,但我仍然想知道是什么导致堆栈溢出。谢谢。 最佳答案
当您在toString
上调用Atom
时,您将获得Traversable
,the documentation描述如下:
默认情况下,此字符串包含此字符串的stringPrefix
集合,然后是所有用逗号分隔并括起来的元素
在括号内。
通过所有集合的TraversableOnce
来实现in foreach
,以实现“所有元素都遵循”。由于您的foreach
首先碰到了Node
本身,因此您立即陷入无休止的循环。