Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion about abbreviating map

Tags:

scala

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)

like image 757
user79074 Avatar asked Dec 25 '22 22:12

user79074


2 Answers

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"))
like image 128
Lee Avatar answered Jan 05 '23 20:01

Lee


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 ).

like image 35
sarveshseri Avatar answered Jan 05 '23 20:01

sarveshseri