【问题标题】:Should I use returns in multiline Scala methods?我应该在多行 Scala 方法中使用返回吗?
【发布时间】:2010-12-20 05:17:47
【问题描述】:

也许这只是我在更命令式编程方面的背景,但我喜欢在我的代码中使用 return 语句。

我知道在 Scala 中,许多方法都不需要返回,因为默认情况下会返回最后一个计算值。我知道这对于“单线”非常有意义,例如

def square(x) = x * x

我也理解使用显式返回的最终情况(当您的代码可能采用多个分支时,并且您想为不同的分支中断该方法,例如,如果发生错误)。但是多行函数呢?如果有明确的返回,它会不会更易读和更有意义,例如

def average(x: List[Int]) : Float = {
  var sum = 0
  x.foreach(sum += _)
  return sum / x.length.toFloat
}

【问题讨论】:

    标签: scala coding-style return


    【解决方案1】:
    def average(x: List[Int]) : Float = 
      x.foldLeft(0)(_ + _) / x.length.toFloat
    

    更新:虽然我的目标是展示如何将迭代代码制成函数式表达式,但@soc 正确地评论说,更短的版本是 x.sum / x.length.toFloat

    我通常发现在 Scala 中我不太需要“在中间返回”。此外,一个大函数被分解成更易于推理的更小的表达式。所以不是

    var x = ...
    if (some condition) x = ...
    else x = ...
    

    我会写 如果(某些条件)... 否则……

    使用匹配表达式也会发生类似的事情。而且你总是可以有帮助嵌套类。

    一旦您对多种形式的表达式感到满意,这些表达式在没有返回语句的情况下计算结果(例如,'if'),那么在您的方法中使用一个看起来不合适。

    在一个工作地点,我们有一条规则,即在方法中间不要有“return”,因为阅读您的代码的人很容易错过它。如果 'return' 只在最后一行,那有什么意义呢?

    【讨论】:

    • 感谢foldLeft,我还没有看到,在我的 Scala 新手中,我试图重新发明轮子
    • def average(x: Int*): Double = x.sum / x.length.toDouble 也应该可以工作。
    【解决方案2】:

    return 没有告诉你任何额外的信息,所以我发现它实际上使我对发生的事情的理解变得混乱。 当然它会返回;没有其他说法!

    摆脱使用return 的习惯也是一个好主意,因为当您使用大量功能代码时,您真的不清楚您将返回到哪里

    def manyFutures = xs.map(x => Futures.future { if (x<5) return Nil else x :: Nil })
    

    return 应该在哪里离开执行?在manyFutures 之外?只是内部块?

    因此,尽管您可以使用显式返回(至少在显式注释返回类型时),但我建议您尝试习惯使用 last-statement-is-the-return-value 自定义。

    【讨论】:

      【解决方案3】:

      您认为带有return 的版本更具可读性可能表明您仍在以强制方式 而非以声明方式 思考。试着从它的角度来考虑你的函数(即它是如何定义的),而不是它做什么(即它是如何计算的)。 p>

      让我们看看您的average 示例,并假设标准库不具备使优雅的单行成为可能的功能。现在在英语中,我们会说数字列表的平均值是列表中数字的总和除以其长度。

      def average(xs: List[Int]): Float = {
         var sum = 0
         xs.foreach(sum += _)
         sum / xs.length.toFloat
      }
      

      此描述与英文版本相当接近,忽略了函数的前两行。我们可以分解出sum 函数以获得更具声明性的描述:

      def average(xs: List[Int]): Float = {
         def sum(xs: List[Int]): Int = // ...
         sum(xs) / xs.length.toFloat
      }
      

      在声明性定义中,return 语句读起来很不自然,因为它明确地将重点放在某事上。

      【讨论】:

        【解决方案4】:

        我不会错过方法末尾的返回语句,因为它是不必要的。此外,在 Scala 中,每个方法都会返回一个值——甚至是不应该返回某些东西的方法。不是void,而是返回类型Unit

        def x { println("hello") }
        

        可以写成:

        def x { println("hello"); return Unit }
        

        但是println 已经返回了 Unit 类型 - 因此,当您明确想要使用返回语句时,您也必须在返回 Unit 的方法中使用它。否则,您将没有连续相同的构建代码。

        但在 Scala 中,有可能通过许多小方法破坏您的代码:

        def x(...): ReturnType = {
          def func1 = ... // use funcX
          def func2 = ... // use funcX
          def func3 = ... // use funcX
          funcX
        }
        

        显式使用的返回语句无助于更好地理解代码。

        Scala 还有一个强大的核心库,可以让你用更少的代码解决很多问题:

        def average(x: List[Int]): Float = x.sum.toFloat / x.length
        

        【讨论】:

          【解决方案5】:

          我认为你不应该使用return,我认为它在某种程度上违背了优雅的概念,即在 Scala 中,一切都是计算结果的表达式。

          就像您的 average 方法一样:它只是一个计算结果为 Float 的表达式,无需返回任何内容即可使其工作。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-03-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-26
            • 2012-11-01
            相关资源
            最近更新 更多