6

I want to write really nice looking idiomatic Scala code list indexOf foo getOrElse Int.MaxValue but now I have to settle for idiotic Java looking code val result = list indexOf foo; if (result < 0) Int.MaxValue else result. Is there a good reason that indexOf in Scala returns Int instead of Option[Int]

pathikrit
  • 32,469
  • 37
  • 142
  • 221
  • I don't know why, probably this question would be better asked on the scala mailing list, but you could easily use the pimp my library pattern and implement your own `indexOf`. – Ende Neu Aug 22 '14 at 21:40
  • According to various talks by Paul Philipps I've watched various aspects of the Scala API are like this because of keeping "compatibility" with Java (or the rest of the programming world?), this should also apply to `indexOf`. You could ask a similar question about the `compareTo` method in `Comparable[A]` which gives you 2^32 possible values instead of just the 3 that are required to express the outcome :). – PermaFrost Aug 22 '14 at 21:55
  • Maybe there is also some arithmetic value for cases like `compareTo` and `indexOf`. – Kigyo Aug 22 '14 at 22:02

3 Answers3

10

It's for compatibility with Java and for speed. You'd have to double-box the answer (first in java.lang.Integer then Option) instead of just returning a negative number. This can take on the order of ten times longer.

You can always write something that will convert negative numbers to None and non-negative to Some(n) if it bothers you:

implicit class OptionOutNegatives(val underlying: Int) extends AnyVal {
  def asIndex = if (underlying < 0) None else Some(underlying)
}
Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
3

It doesn't have to be like that.

scala> "abcde" index 'c'
res0: psp.std.Index = 2

scala> "abcde" index 'z'
res1: psp.std.Index = -1

scala> "abcde" index 'z' match { case Index(n) => n ; case _ => MaxInt }
res2: Int = 2147483647

// Emphasizing that at the bytecode level we still return an Int - no boxing.
scala> :javap psp.std.SeqLikeExtensionOps
[...]
public abstract int index(A);
  descriptor: (Ljava/lang/Object;)I

That's from psp-std, you can run "sbt console" and then the above.

psp
  • 12,138
  • 1
  • 41
  • 51
  • 1
    Do you know what is the point of this: http://www.scala-lang.org/api/current/#scala.collection.Searching$? It seems to implement what I want with Found i.e. Some(index) and InsertionPoint i.e. None ADTs. – pathikrit Apr 13 '15 at 04:26
1

To address the secondary question, squeezed between the primary and tertiary ones, there are other methods for doing things like processing indices and finding or collecting elements that satisfy a predicate.

scala> ('a' to 'z').zipWithIndex find (_._1 == 'k') map (_._2)
res6: Option[Int] = Some(10)

Usually you're doing something interesting with the element you find.

som-snytt
  • 39,429
  • 2
  • 47
  • 129