Bartłomiej Szałach Bartłomiej Szałach - 26 days ago 4
Scala Question

Obtaining array element in Scala works only with explicit apply method

Accessing collection elements in Scala is done by

apply
method. Having said that I tried to read numbers from standard input and get the second one as int in just one line.

def main(args: Array[String]): Unit = {
val number = StdIn.readLine().split(" ").map(_.toInt)(1)
}


IntelliJ marks this
1
and show the error (the same is shown after the compilation attempt):


Error:(11, 60) type mismatch; found : Int(1) required:
scala.collection.generic.CanBuildFrom[Array[String],Int,?]
val number = StdIn.readLine().split(" ").map(_.toInt)(1)


Folding the expression in the parentheses dosn't help as well. However, when I split mapping input to int array and getting the element to other lines, everything works fine.

def main(args: Array[String]): Unit = {
val numbers = StdIn.readLine().split(" ").map(_.toInt)
numbers(1)
}


The explicit invocation of
apply
also does the job:

val number = StdIn.readLine().split(" ").map(_.toInt).apply(1)


Why does this weird behaviour happens? Obtaining element via
array(5)
is just a shortcut for
array.apply(5)
, isn't it?

Answer

As compiler already pointed out, map is defined with two arg lists. second one containing a single implicit param: implicit bf: CanBuildFrom[Repr, B, That]

For a vast majority of scenarios, the users don't worry about specifying the second arg. Specifically, in your case this is what the compiler "figures out":

StdIn.readLine().split(" ").map(_.toInt)(Array.canBuildFrom[Int])

So, if writing out apply is not desired then the following is the only choice:

StdIn.readLine().split(" ").map(_.toInt)(Array.canBuildFrom[Int])(1)

Suggested reading: