10

我是 Scala 的新手,只是在阅读Scala By Example。在第 2 章中,作者有 2 个不同版本的 Quicksort。

一种是命令式风格:

def sort(xs: Array[Int]) {
    def swap(i: Int, j: Int) {
        val t = xs(i); xs(i) = xs(j); xs(j) = t
    }
    def sort1(l: Int, r: Int) {
        val pivot = xs((l + r) / 2)
        var i = l; var j = r
        while (i <= j) {
            while (xs(i) < pivot) i += 1
            while (xs(j) > pivot) j -= 1
            if (i <= j) {
                swap(i, j)
                i += 1
                j -= 1
            }
        }
        if (l < j) sort1(l, j)
        if (j < r) sort1(i, r)
    }
    sort1(0, xs.length - 1)
}

一是功能风格:

def sort(xs: Array[Int]): Array[Int] = {
  if (xs.length <= 1) xs
  else {
    val pivot = xs(xs.length / 2)
    Array.concat(
      sort(xs filter (pivot >)),
           xs filter (pivot ==),
      sort(xs filter (pivot <)))
  }
}

函数式风格相对于命令式风格的明显优势是简洁。但是性能呢?由于它使用递归,我们是否像在其他命令式语言(如 C)中那样为性能损失付出代价?或者,Scala 是一种混合语言,首选“Scala 方式”(函数式),因此效率更高。

注意:作者确实提到了函数式样式确实使用了更多的内存。

4

1 回答 1

12

这取决于。如果您查看 Scala 源代码,通常会在“底层”使用命令式样式以提高性能 - 但在许多情况下,正是这些调整允许编写高性能的函数式代码。所以通常你可以想出一个足够快的功能解决方案,但你必须小心并知道你在做什么(尤其是关于你的数据结构)。例如,第二个示例中的数组 concat 不太好,但可能还不错——但在这里使用列表并用 ::: 连接它们会有点过头了。

但是,如果您不实际测量性能,那只不过是有根据的猜测。在复杂的项目中,很难预测性能,尤其是当对象创建和方法调用等事情越来越多地被编译器和 JVM 优化时。

我建议从功能风格开始。如果速度太慢,请对其进行分析。通常有更好的功能解决方案。如果没有,您可以使用命令式风格(或两者兼而有之)作为最后的手段。

于 2010-07-25T11:47:05.817 回答