Why does Scala's indexOf (in List etc) return Int instead of Option[Int]?
Asked Answered
P

3

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]

Pyonephritis answered 22/8, 2014 at 21:32 Comment(3)
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.Mercurialize
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 :).Phosphor
Maybe there is also some arithmetic value for cases like compareTo and indexOf.Tog
D
4

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.

Decade answered 24/8, 2014 at 15:24 Comment(1)
Do you know what is the point of this: 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.Pyonephritis
G
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)
}
Gash answered 22/8, 2014 at 22:13 Comment(0)
D
4

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.

Decade answered 24/8, 2014 at 15:24 Comment(1)
Do you know what is the point of this: 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.Pyonephritis
D
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.

Derna answered 23/8, 2014 at 2:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.