在尝试编写一个简单的括号平衡函数时,我了解到我不知道scala如何评估if语句。
def balance(chars: List[Char]): Boolean = {
def loop(chars: List[Char], opened: Int): Boolean = {
println(opened)
println(chars.head)
if (opened < 0) return false
if (chars.isEmpty && opened == 0) return true
if (chars.isEmpty && opened > 0) return false
if (!chars.isEmpty && chars.head.toString == "(") loop(chars.tail, opened+1)
if (!chars.isEmpty && chars.head.toString == ")") loop(chars.tail, opened-1)
else loop(chars.tail, opened)
}
loop(chars, 0)
}
当我运行它时,通过第三次迭代,它将println(打开)并声明打开= -1。我想象(打开&lt; 0)----&gt; (-1&lt; 0)-----&gt;是的,所以我会回复假。事实并非如此 - 为什么?
答案 0 :(得分:2)
Scala按照声明的顺序评估if
个表达式。这个算法的问题在于它假设只有在没有其他else
条件为真的情况下才会评估最后的if
表达式,但是如果输入'(X)'',则会创建两个递归树:一个用于条件!chars.isEmpty && chars.head.toString == "("
,另一个用于else loop(chars.tail, opened)
。这会产生一种印象,即当打开= -1时递归没有结束,但事实上你所看到的是'else'递归树。
解决方案?您只是错过了else
:
if (!chars.isEmpty && chars.head.toString == "(") loop(chars.tail, opened+1) **else**
(注意:可以使用match...case
语句改进此代码。这将阻止先前的else
问题发生。
此外,您可以将字符与字符进行比较。无需将其转换为字符串:chars.head.toString == "("
=&gt; chars.head == '('
)
*编辑* 在您发表评论之后,您可以在列表结构中使用模式匹配:
def loop(chars: List[Char], opened: Int): Boolean = {
if (opened < 0) return false else
chars match {
case Nil => opened == 0
case '('::tail => loop(tail, opened + 1)
case ')'::tail => loop(tail, opened -1)
case x::tail => loop(tail, opened)
}
我希望这会有所帮助。