【问题标题】:Which construction for iteration is better to use in Scala? [closed]在 Scala 中使用哪种迭代结构更好? [关闭]
【发布时间】:2014-09-30 10:50:35
【问题描述】:

最近,我开始在 Scala 中编写很多我的编程竞赛。 (您可以在这里查看平台 - http://codeforces.com/

关于问题的性质,我经常需要遍历数组或输入数据。例如。有一个问题陈述,它说,在第一行输入我会得到数字 M 然后我需要读取 M 行,或者整数或其他什么。我尝试为此使用不同的方法:

for (i <- 0 until M)
---- 
(0 until M).foreach
----
var i = 0
while (i < M)
---

甚至是尾递归

@tailrec
  def recursion(i: Int): Unit = {
    if (i < M) {
      doSomething()
      recursion(i + 1)
    }
  }

那么,我的问题是哪种结构更适合使用 Scala 风格和更好的性能? (我正在解决的问题往往需要快速执行,否则不会通过)

附: 我为此编写了一个小测试,看起来 while 和 tailrec 是表现最好的,但不是一个大问题。你可以看这里 - https://gist.github.com/MysterionRise/5daa63fdbd5d058528fe

【问题讨论】:

    标签: performance scala coding-style


    【解决方案1】:

    关于性能:

    请注意,如果您想在 JVM 上编写适当的微基准测试,您必须考虑到 many effects - 例如,同一段代码的性能会随着 JVM 开始使用 JIT 编译而发生变化,然后尝试不同的优化。要在 Scala 中编写适当的基准测试,您可以查看诸如 ScalaMetercaliper 之类的库。顺便说一句,第二个链接比较了在 Scala 中循环的不同方式,因此它应该很容易适应您的用例。

    但是,一般来说:

    • 尾递归解决方案将优化为由等效的 while 循环生成的相同类型的字节码,因此两者应该始终相似(如果代码确实等效)。
    • for 循环是调用 foreach 方法的语法糖,因此两者应该严格等价。
    • foreach(或 for 循环)比等效的 while 循环(或尾递归)要慢一些:我上面链接的 benchmark 显示 1000 次以上迭代的性能差异为 15 倍(尽管它可能取决于Scala 和 JRE 的版本......)。但是,如果循环内的代码执行时间比循环本身长得多,那么这种差异将变得可以忽略不计,因此这并不意味着它总是相关的。

    关于风格:

    我完全同意 johanandren 的回答。

    【讨论】:

      【解决方案2】:

      我会按以下顺序对它们的风格进行评分:

      • for/foreach
      • 尾递归
      • 势在必行的时候(风格上的最后手段)

      在性能方面,尾递归和命令式可以让您尽可能快地进行循环(tailrec 在实践中将变得非常接近 while 循环),并且比 for/foreach 更快。

      附注:如果您要使用理想化的 Scala,您可能希望尽量避免副作用,而是使用 .map 或让您的尾递归函数返回一些东西而不是改变一些东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-06
        • 1970-01-01
        • 2012-02-16
        • 1970-01-01
        • 2020-01-25
        • 2019-11-23
        • 1970-01-01
        相关资源
        最近更新 更多