无限循环scala代码

San*_*der 5 loops scala case pattern-matching

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
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

提前致谢!

Tom*_*icz 9

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

simplify(prop)
Run Code Online (Sandbox Code Playgroud)

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

...simplify(simplify(simplify(simplify(simplify(simplify(simplify(prop)))))))
Run Code Online (Sandbox Code Playgroud)

但是修复(基于您的代码)很简单:

if (simplify(prop) == prop) prop
    else prop
Run Code Online (Sandbox Code Playgroud)

只需用......替换它

 case _ => prop
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Sander:你能告诉我们不是简化'Not(Not(a))`的输入吗?这可以通过在单独的术语上调用`simplify()`来解决,例如:简化`和(不(不(a)),b)`你必须返回`和(简化(不(不)(a)),简化(b))`(简化模式是:`和(a,b)=>和(简化(a),简化(b))`. (2认同)

Tra*_*own 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
}
Run Code Online (Sandbox Code Playgroud)