【问题标题】:Different outputs when stating return or not声明退货时的不同输出
【发布时间】:2016-05-13 09:27:56
【问题描述】:

我是 scala 的新手,我正在尝试通过编写一个简单的程序来检查是否给定一个字符串,每个左括号都有自己的右括号。 例如对于字符串“{{ssss{{}}}}}”,答案应该是错误的。 我使用的代码如下:

package recfun
import common._
import scala.collection.mutable.Stack

object Main{
def main(args: Array[String]) {
 println(balance("{{ssss{{}}}}}".toList))
}

def balance(chars: List[Char]): Boolean = {

 val openParentheses : List[Char] = List('(','{','[')
 val matchingParentheses = Map(
   '}'-> '{',
   ']'->'[',
   ')'->'(');

 val openParenthesesFound: Stack[Char] = Stack[Char]()

 for (letter <- chars) {
   if (openParentheses.contains(letter)) openParenthesesFound.push(letter)
   else if (matchingParentheses.contains(letter)) {
     if (openParenthesesFound.isEmpty || !openParenthesesFound.head.equals(matchingParentheses(letter))) return false
     else
       openParenthesesFound.pop
   }
 }

 if (openParenthesesFound.nonEmpty) false else true
 }
}

但是,在行中

if (openParenthesesFound.isEmpty || !openParenthesesFound.head.equals(matchingParentheses(letter))) return false
else
  openParenthesesFound.pop

如果我按照 IntellijIdea 的建议删除“return”,则程序将失败并且我得到错误答案:True。

谁能帮我解释一下为什么会这样?我可能错过了一些东西。 另外,有没有人对这类任务有更好的解决方案?

非常感谢您的帮助, 乔瓦尼

【问题讨论】:

    标签: scala


    【解决方案1】:

    Intellij 是错误的。显然,删除 return 语句会改变函数的逻辑。 也许,这意味着要告诉您的是,在 scala 中使用 return 语句通常是不受欢迎的。通常最好想出一个避免它的解决方案。可变状态实际上也是如此......

    这样的事情是其中一种可能性:

      val parens = "{[(" zip "}])" toMap
    
      object OpenP {
         def unapply(c: Char) = parens.keys.find(_ == c)
      }
      object CloseP {
         def unapply(c: Char) = parens.values.find(_ == c)
      }
    
      @tailrec
      def balanced(s: List[Char], ps: List[Char] = Nil): Boolean = (ps, s) match {
         case (stack, Nil) => stack.isEmpty
         case (p :: stack, CloseP(c) :: tail) => c == parens(p) && balanced(tail, stack)
         case (stack, OpenP(p) :: tail) => balanced(tail, p :: stack)
         case (stack, c :: tail) => balanced(tail, stack)
       }
    

    【讨论】:

      【解决方案2】:

      您的代码流将根据您是否在此处的for 理解中间使用return 而发生重大变化。

      如果您使用return,您的balance 方法将在您第一次进入该代码路径时以false 退出,这似乎是您想要的(当您遇到第一个不匹配时返回false括号,因为您要求不存在)。

      如果您不使用return,则只有包含if-else 的块将评估为假(请记住,Scala 中的所有内容都是一个表达式)而不是退出整个方法。由于您没有分配或检查它,因此您的检查实际上几乎什么也没做,您将循环整个事情,最后一条语句返回true。所以如果你想以这种方式解决这个问题,你需要return

      但是,Scala 鼓励没有可变状态的函数式编程风格(例如您的 Stack 此处)。以这种方式解决此问题的最简单方法可能是递归并使用累加器来存储中间括号堆栈 - 这样您就不需要可变状态(vars 或可变集合)。并且您避免使用显式 returns (这是鼓励的 - 也可能是您的 IDE 通知您其使用的原因),因为方法隐式返回其最后一条语句作为其值,这通常很容易通过递归方法实现.

      【讨论】:

        猜你喜欢
        • 2011-03-30
        • 2022-11-18
        • 2011-08-10
        • 2013-07-13
        • 2012-10-04
        • 2013-07-11
        • 1970-01-01
        • 2017-06-06
        • 1970-01-01
        相关资源
        最近更新 更多