如何在Scala中突破或退出void方法?

时间:2016-11-13 19:58:47

标签: scala

这是一个非常基本的问题,但我无法在任何地方找到答案。在没有返回值的Scala方法中,如何提前退出方法?

例如,

def printPositiveNumbersSum (n1: Int, n2: Int) = {
    if (n1 < 0 || n2 < 0)
        // How do I break out of this method here?
    println(n1 + n2)
}

尝试在Java中使用return会引发printPositiveNumbersSum没有返回类型的错误。

我知道我可以将它作为if-else语句,但是如果有多个条件我想退出该方法并返回其调用者,那么这很快就会变得难以处理。

3 个答案:

答案 0 :(得分:5)

您需要从方法中指定单位返回类型

   def printPositiveNumbersSum(n1: Int, n2: Int): Unit = {
     if (n1 < 0 || n2 < 0)
       return
     println(n1 + n2)
   }

然后它让scala编译器感到高兴。

答案 1 :(得分:2)

基本问题的习惯是比他们看起来更有趣。有几种方法可以解决这个问题,可能值得考虑作为替代方案。但基础是,一切都返回某种类型的值,编译器试图找出该类型是什么。在您的情况下,printPostiveNumbersSum会返回某种类型的内容。

  • 让你的方法返回一个单位。类型Unit表示函数或可执行代码段。这个答案已经提到了。
  • 考虑为总和返回Option [Int]。如果验证成功,则返回Some(sum),如果失败,则返回None。然后,调用者可以决定在失败的情况下做什么,可能使用match { case Some(sum)...构造。

    def positiveNumbersSum (n1: Int, n2: Int): Option[Int] = {
      if (n1 < 0 || n2 < 0)
        None
      else Some(n1 + n2)
    }
    
  • 但是在更复杂的情况下,当您可能需要考虑更多规则时,为失败返回原因可能很方便,而不仅仅是返回None。在这种情况下,我发现Either方便。您可以指定两种返回类型。同样,调用者可以使用match { case Left(reason)... case Right(sum)...构造进行区分。

    def positiveNumbersSum (n1: Int, n2: Int): Either[String,Int] = {
      if (n1 < 0 || n2 < 0)
        Left("One of the numbers is negative")
      else Right(n1 + n2)
    }
    

答案 2 :(得分:1)

您可以翻转逻辑并避免使用return关键字。

def printPositiveNumbersSum (n1: Int, n2: Int) = {
  if (n1 >= 0 && n2 >= 0)
    println(n1 + n2)
}

您不应该有一个方法的多个退出点,如果您发现自己遇到此问题,则应重新评估您的解决方案。

scala中的return关键字也有点不直观。如果您有Int对的列表,并且想要迭代列表,打印所有有效对,则可以编写如下函数:

def printMany(l: List[(Int, Int)]): Unit =
    l.foreach { case (n1, n2) =>
      if (n1 < 0 || n2 < 0) return
      println(n1 + n2)
    }

现在,在这种情况下,返回关键字究竟要做什么?如果给出一个列表val l = List((1,1), (2,2), (-1, 2), (5,4)),它将打印2,4,然后它将停止。 return关键字从整个方法返回,而不是嵌套的lambda。

出于这个原因,最好避免在scala中使用return返回。