Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do Scala's index methods return -1 instead of None if the element is not found?

Tags:

scala

I've always been wondering why in Scala the various index methods for determining the position of an element in a collection (e.g. List.indexOf, List.indexWhere) return -1 to indicate the absence of the given element in the collection, instead of a more idiomatic Option[Int]. Is there some particular advantage to returning -1 instead of None, or is this just for historical reasons?

like image 821
python dude Avatar asked Dec 31 '12 01:12

python dude


People also ask

What will be returned if you look for the index of something that does not exist?

The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.

How do you get the index of an element in a list in Scala?

Scala List indexOf() method with example. The indexOf() method is utilized to check the index of the element from the stated list present in the method as argument. Return Type: It returns the index of the element present in the argument.


2 Answers

It is just for historical reasons, but then one wants to know what the historical reasons are: what was the history, and why did it turn out that way?

The immediate history is the java.lang.String.indexOf method, which returns the index, or -1 if no matching character is found. But this is hardly new; the Fortran SCAN function returns 0 if no character is found in a string, which is the same thing given that Fortran uses 1-indexing.

The reason to do this is that strings have only positive length, so any negative length can be used as a None value without any overhead of boxing. -1 is the most convenient negative number, so that's it.

And this can add up if the compiler isn't smart enough to realize that all the boxing and unboxing and everything is irrelevant. In particular, an object creation tends to take 5-10 ns, while a function call or comparison typically takes more like 1-2 ns, so if the collection is short, creating a new object can have a sizable fractional penalty (more so if your memory is already taxed and the GC has a lot of work to do).

If Scala had initially had an amazing optimizer, then the choice probably would have been different, as one would just write things with options, which is safer and less of a special case, and then trust the compiler to convert it into appropriately high-performance code.

like image 100
Rex Kerr Avatar answered Oct 23 '22 03:10

Rex Kerr


Speed? (not sure)

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

And you also should always check for index < 0 in Some(index)

like image 34
idonnie Avatar answered Oct 23 '22 01:10

idonnie