Scala方式来编程一堆if

And*_*rey 16 functional-programming scala

我开始使用scala,并尝试应用功能方式,但我出来了一堆嵌套if\else结构很难读,我想知道有更好的方法来编程这样的东西?例如,我写了脚本,执行括号平衡

def balance(chars: List[Char]): Boolean = {
    def checkParentesys(chars: List[Char], parentesis: List[Char]): Boolean =
      if (chars.isEmpty && parentesis.isEmpty)
        true
      else
        if (chars.head == '(')
            checkParentesys(chars.tail, '(' :: parentesis)
        else
            if (parentesis.isEmpty)
                false
            else
                checkParentesys(chars.tail, parentesis.tail)

    checkParentesys(chars.filter(s => s == '(' || s == ')'), List())
  }
Run Code Online (Sandbox Code Playgroud)

你能建议,我怎样才能把它写得更实用,更像scala?

Lui*_*hys 27

把它写成折叠可能更好:

def balance(chars: List[Char]): Boolean = chars.foldLeft(0){
  case (0, ')') => return false
  case (x, ')') => x - 1
  case (x, '(') => x + 1
  case (x, _  ) => x
} == 0
Run Code Online (Sandbox Code Playgroud)

  • 我觉得用"回归"是不好的风格? (3认同)
  • 不总是.初学者,特别是来自Java的初学者,往往过度使用`return`.但是,这里需要`return`才能从折叠中退出.当然还有其他方法可以解决这个问题(参见其他答案),但这个方法对我来说似乎相当优雅,即使是`return`. (2认同)

ste*_*tew 19

我认为没有任何理由在遍历之前过滤列表.您可以在遍历列表时忽略非括号.我认为没有必要建立第二个列表.你真正想知道的是,开括号的计数从来都不是负数:

def balance(chars: List[Char]): Boolean = {
  @tailrec
  def _balance(chars: List[Char], count: Int) : Boolean = 
    chars match {
        case Nil => count == 0   // end of the string did we close every open?
        case '(' :: xs => _balance(xs, count+1)  
        case ')' :: xs => (count > 0) && _balance(xs, count-1) 
        case _ => _balance(chars.tail, count) // uninteresting char, skip it
    }

  _balance(chars, 0)
}
Run Code Online (Sandbox Code Playgroud)

  • 而不是`_balance`使用`loop`或`go`或其他东西.第一种不符合非官方风格指南. (2认同)