最近,我开始编写很多我在 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风格和更好的性能? (我正在解决的问题通常需要快速执行,否则它们不会被传递)
附:
我为此写了一个小测试,看起来虽然和tailrec是最好的表演者,但不是一件大事.你可以在这看看 – https://gist.github.com/MysterionRise/5daa63fdbd5d058528fe
请注意,如果要在JVM上编写适当的微基准测试,则必须考虑many effects – 例如,当JVM开始使用JIT编译时,同一段代码的性能将首先变化,然后尝试不同的优化.要在Scala中编写适当的基准测试,您可以查看像ScalaMeter或caliper这样的库.顺便提一下,第二个链接比较了在Scala中循环的不同方式,因此应该很容易适应您的用例.
但是,一般来说:
>尾递归解决方案将针对由等效while循环生成的相同类型的字节码进行优化,因此两者应始终相似(如果代码实际上是等效的).
> for循环是用于调用foreach方法的语法糖,因此两者应该是严格等价的.
> foreach(或for循环)比等效的while循环(或尾递归)慢一些:上面链接的benchmark显示了1000次迭代的15x性能差异(尽管它可能取决于Scala的版本和版本的JRE ……).但是如果循环中的代码执行的时间比循环本身要长得多,那么这种差异将变得微不足道,因此这并不意味着它总是相关的.
关于风格:
我完全同意约翰丹德的回答.