更有效的尾递增解决方案?

时间:2014-05-30 21:30:01

标签: scala tail-recursion

我对公式有以下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
}

现在终于回答了问题。哪种解决方案在效率方面更可取?至少我发现我简单的第一个解决方案更具美感。

1 个答案:

答案 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))
}