我在 Scala 中有一个简单的树结构,如下所示:
sealed abstract class FactsQueryAst[FactType] {
}
object FactsQueryAst {
case class AndNode[FactType](subqueries: Seq[FactsQueryAst[FactType]]) extends FactsQueryAst[FactType]
case class OrNode[FactType](subqueries: Seq[FactsQueryAst[FactType]]) extends FactsQueryAst[FactType]
case class Condition[FactType](fact: FactType, value: FactValue) extends FactsQueryAst[FactType]
}
是否有任何相对简单的方法可以使这个结构与 map、foldLeft 或 filter 等高阶函数一起工作?有一篇关于为您自己的集合实现 Traversable 特征的好文章(http://daily-scala.blogspot.com/2010/04/creating-custom-traversable.html),但是对于树案例来说,它似乎过于复杂,或者在至少我错过了一些主要的东西。
UPD。我尝试如下实现天真的 Traversable ,但它导致无限循环仅用于打印值。
sealed abstract class FactsQueryAst[FactType] extends Traversable[FactsQueryAst.Condition[FactType]]
object FactsQueryAst {
case class AndNode[FactType](subqueries: Seq[FactsQueryAst[FactType]]) extends FactsQueryAst[FactType] {
def foreach[U](f: (Condition[FactType]) => U) {subqueries foreach {_.foreach(f)}}
}
case class OrNode[FactType](subqueries: Seq[FactsQueryAst[FactType]]) extends FactsQueryAst[FactType] {
def foreach[U](f: (Condition[FactType]) => U) {subqueries foreach {_.foreach(f)}}
}
case class Condition[FactType](fact: FactType, value: FactValue) extends FactsQueryAst[FactType]{
def foreach[U](f: (Condition[FactType]) => U) {f(this)}
}
}
无限循环的堆栈跟踪如下所示:
at tellmemore.queries.FactsQueryAst$Condition.stringPrefix(FactsQueryAst.scala:65532)
at scala.collection.TraversableLike$class.toString(TraversableLike.scala:639)
at tellmemore.queries.FactsQueryAst.toString(FactsQueryAst.scala:5)
at java.lang.String.valueOf(String.java:2854)
at scala.collection.mutable.StringBuilder.append(StringBuilder.scala:197)
at scala.collection.TraversableOnce$$anonfun$addString$1.apply(TraversableOnce.scala:322)
at tellmemore.queries.FactsQueryAst$Condition.foreach(FactsQueryAst.scala:23)
at scala.collection.TraversableOnce$class.addString(TraversableOnce.scala:320)
at tellmemore.queries.FactsQueryAst.addString(FactsQueryAst.scala:5)
at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:286)
at tellmemore.queries.FactsQueryAst.mkString(FactsQueryAst.scala:5)
at scala.collection.TraversableLike$class.toString(TraversableLike.scala:639)
at tellmemore.queries.FactsQueryAst.toString(FactsQueryAst.scala:5)
at java.lang.String.valueOf(String.java:2854)
at scala.collection.mutable.StringBuilder.append(StringBuilder.scala:197)
at scala.collection.TraversableOnce$$anonfun$addString$1.apply(TraversableOnce.scala:322)
at tellmemore.queries.FactsQueryAst$Condition.foreach(FactsQueryAst.scala:23)