9

我一直想知道为什么在 Scala 中用于确定集合中元素位置的各种索引方法(例如List.indexOf, List.indexWhere)返回-1以指示集合中不存在给定元素,而不是更惯用的Option[Int]. 返回-1而不是返回是否有一些特别的优势None,或者这只是出于历史原因?

4

3 回答 3

8

只是出于历史原因,但后来人们想知道历史原因是什么:历史是什么,为什么会变成这样?

直接历史是java.lang.String.indexOf返回索引的方法,如果没有找到匹配的字符,则返回 -1。但这并不新鲜。如果在字符串中找不到任何字符,Fortran SCAN 函数将返回 0,这与 Fortran 使用 1 索引相同。

这样做的原因是字符串只有正长度,因此任何负长度都可以用作None值,而无需任何装箱开销。 -1是最方便的负数,就是这样。

如果编译器不够聪明,无法意识到所有装箱和拆箱以及一切都无关紧要,这可能会加起来。特别是,创建一个对象往往需要 5-10 ns,而函数调用或比较通常需要 1-2 ns,所以如果集合很短,创建一个新对象可能会有相当大的分数损失(如果你的内存已经被征税了,GC 有很多工作要做)。

如果 Scala 最初有一个了不起的优化器,那么选择可能会有所不同,因为人们只会用选项编写东西,这样更安全且不是特殊情况,然后相信编译器会将其转换为适当的高性能代码。

于 2012-12-31T14:22:35.560 回答
1

速度?(没有把握)

def a(): Option[Int] = Some(Math.random().toInt)
def b(): Int = Math.random().toInt
val t0 = System.nanoTime; (0 to 1000000).foreach(_ => a()); println("" + (System.nanoTime - t0))
// 53988000
val t0 = System.nanoTime; (0 to 1000000).foreach(_ => b()); println("" + (System.nanoTime - t0))
// 49273000

而且您还应该始终检查 index < 0 inSome(index)

于 2012-12-31T01:46:19.053 回答
0

还有一个好处是只返回一个Int可以使用Java的内置类型,而Option[Int]需要将整数包装在一个Object. 这意味着更差的速度(如@idonnie 所示)但也意味着更多的内存使用。

虽然Option作为通用工具很棒(我经常使用它),但其他非值表示 saDouble.NaN或空字符串也是完全有效且有用的。

使用的好处之一是能够将其作为集合Option传递给循环等。for如果您不太可能这样做,请检查 -1 或者NaN可能比为None/进行匹配更简洁Some

于 2012-12-31T09:47:09.753 回答