I would have thought the following code:
val a = Array(1, 2, 3, 4, 5)
println(a.map(n => "x"))
Could be abbreviated to:
val a = Array(1, 2, 3, 4, 5)
println(a.map("x"))
But the latter gives me the exception below. Why is this?
java.lang.StringIndexOutOfBoundsException: String index out of range: 1 java.lang.StringIndexOutOfBoundsException: String index out of range: 1 at java.lang.String.charAt(String.java:658) at scala.collection.immutable.StringLike$class.apply(StringLike.scala:52) at scala.collection.immutable.WrappedString.apply(WrappedString.scala:33) at scala.collection.immutable.WrappedString.apply(WrappedString.scala:33) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245) at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) at scala.collection.mutable.ArrayOps$ofInt.foreach(ArrayOps.scala:234) at scala.collection.TraversableLike$class.map(TraversableLike.scala:245) at scala.collection.mutable.ArrayOps$ofInt.map(ArrayOps.scala:234)
Strings
are also functions Int => Char
which fetches the char at the given index into the string. Therefore
a.map("x")
is equivalent to
a.map(i => "x".charAt(i))
The first element of a
is 1
so this will try to find the char at index 1 in the string x
which is out of range, hence the exception.
If you want a function that always returns "x"
then you can use Function.const
:
import Function.const
a.map(const("x"))
In scala String
is just a placeholder type for java.lang.Strings
.
All instances of String
are implicitly converted to scala.collection.immutable.StringOps
which extends trait StringLike[ String ]
which in-turn extends trait IndexedSeqOptimized[Char, String]
.
Now, trait IndexedSeqOptimized[Char, String]
defines an abstract apply method apply(index: Int): Char
which is implemented by trait StringLike[ String ]
.
Hence each String instance like val s = "A String"
can be used as a function of type Int => Char
like this - val c = s( 0 )
.
Now, your a.map( "x" )
is equivalent to a.map( i => "x".apply( i ) )
or a.map( "x".apply( _ ) )
or a.map( i => ( "x" )( i ) )
or simply a.map( "x".apply )
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With