无限循环scala代码

时间:2012-02-25 21:50:23

标签: scala loops pattern-matching case

object Prop {
  def simplify(prop : Prop) : Prop = {
    prop match {
      case Not(Or(a,b)) => simplify(And(Not(a),Not(b)))
      case Not(And(a,b)) => simplify(Or(Not(a),Not(b)))
      case Not(Not(a)) => simplify(a)
      case _ => {
        if (simplify(prop) == prop) prop
        else prop
      }
    }
  }
}

我很确定我的'默认'案例导致了无限循环。我在所有情况下都使用递归。这意味着,但是,只有简化了Prop。一旦道具不能简化,就应该归还整个事物。

我看不出如何测试任何进一步的简化。 (我不允许使用其他库,如freenodes #scala频道所示。)

有人可以解释是否是'case _'导致循环,以及如何解决它?如何在不进行循环的情况下测试可能的简化?

提前致谢!

3 个答案:

答案 0 :(得分:9)

很明显发生了什么,你使用默认的case是正确的。如果您的输入prop与您要调用的任何案例都不匹配:

simplify(prop)

使用相同的参数。因为之前它导致了simplify()的递归调用,并且您使用相同的输入调用函数,它再次输入simplify()。所以这不是一个无限循环,而是永远不会终止递归调用:

...simplify(simplify(simplify(simplify(simplify(simplify(simplify(prop)))))))

然而,修复(基于您的代码)很简单:

if (simplify(prop) == prop) prop
    else prop

只需将其替换为......

 case _ => prop

两个分支都返回相同的值。如果您考虑一段时间,这实际上是正确的。您有一组优化。如果它们都不匹配您的表达式,则意味着它不再被简化。因此,你按原样返回。

BTW看起来像是在使用case类进行布尔表达式简化。您可能会对我的article感兴趣,但我会使用算术表达式。

答案 1 :(得分:6)

问题在于你试图在一个步骤中做两件事,需要按顺序发生 - 应用De Morgan定律(并删除双重否定)并递归地简化任何孩子。这就是为什么只将case And(a, b) => And(simplify(a), simplify(b))放入match将无效。

尝试以下方法:

val deMorganAndDoubleNegation: Prop => Prop = {
  case Not(Or(a, b)) => And(Not(a), Not(b))
  case Not(And(a, b)) => Or(Not(a), Not(b))
  case Not(Not(a)) => a
  case a => a
}

val simplify: Prop => Prop = deMorganAndDoubleNegation andThen {
  case And(a, b) => And(simplify(a), simplify(b))
  case Or(a, b) => Or(simplify(a), simplify(b))
  case Not(a) => Not(simplify(a))
  case a => a
}

答案 2 :(得分:2)

是的,默认情况是导致循环。 if (simplify(prop) == prop) prop是有问题的。 您无需测试是否可以进一步简化,因为当您处于默认情况下时,会尝试所有可能的简化。