我对公式有以下ADT。 (缩写为重要的)
sealed trait Formula
case class Variable(id: String) extends Formula
case class Negation(f: Formula) extends Formula
abstract class BinaryConnective(val f0: Formula, val f1: Formula) extends Formula
请注意,以下方法是在公式的隐式类中定义的。
我想说我想从公式中获取所有变量。
我的第一个方法是:
解决方案1
def variables: Set[Variable] = formula match {
case v: Variable => HashSet(v)
case Negation(f) => f.variables
case BinaryConnective(f0, f1) => f0.variables ++ f1.variables
case _ => HashSet.empty
}
这种方法很容易理解,但不是尾递。所以我想尝试不同的东西。我在树状公式上实现了foreach
。
解决方案2
def foreach(func: Formula => Unit) = {
@tailrec
def foreach(list: List[Formula]): Unit = list match {
case Nil =>
case _ => foreach(list.foldLeft(List.empty[Formula])((next, formula) => {
func(formula)
formula match {
case Negation(f) => f :: next
case BinaryConnective(f0, f1) => f0 :: f1 :: next
case _ => next
}
}))
}
foreach(List(formula))
}
现在我可以在foreach
。
def variables2 = {
val builder = Set.newBuilder[Variable]
formula.foreach {
case v: Variable => builder += v
case _ =>
}
builder.result
}
现在终于回答了问题。哪种解决方案在效率方面更可取?至少我发现我简单的第一个解决方案更具美感。
答案 0 :(得分:1)
我希望解决方案2更有效率,因为您不会创建许多不同的HashSet
实例并将它们组合在一起。它也更通用。
您可以简化解决方案2,删除foldLeft
:
def foreach(func: Formula => Unit) = {
@tailrec
def foreach(list: List[Formula]): Unit = list match {
case Nil =>
case formula :: next => {
func(formula)
foreach {
formula match {
case Negation(f) => f :: next
case BinaryConnective(f0, f1) => f0 :: f1 :: next
case _ => next
}
}
}
}
foreach(List(formula))
}