scala> val shares = Map("Apple" -> 23, "MicroSoft" -> 50, "IBM" -> 17)
shares: scala.collection.immutable.Map[java.lang.String,Int]
= Map(Apple -> 23, MicroSoft -> 50, IBM -> 17)
scala> val shareholders = shares map {_._1}
shareholders: scala.collection.immutable.Iterable[java.lang.String]
= List(Apple, MicroSoft, IBM)
scala> val newShares = shares map {case(k, v) => (k, 1.5 * v)}
newShares: scala.collection.immutable.Map[java.lang.String,Double]
= Map(Apple -> 34.5, MicroSoft -> 75.0, IBM -> 25.5)
From this example it seems like the map
method is overloaded on return type. Overloading on return type is not possible right? Would somebody please explain what's going on here?
map
isn't overloaded on return type. Instead, there is one method with an abstract return type.
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
In the bytecode, this is erased to Object
:
public abstract java.lang.Object map(scala.Function1, scala.collection.generic.CanBuildFrom);
The pattern is described best in the paper Fighting Bit Rot with Types
This isn't what's going on in this case, but actually yes, overloading on return type is supported by JVM. This is exposed in Scala for methods which have different generic argument types which erase to the same type. The example given at the link is
object Overload{
def foo(xs : String*) = "foo"; // after erasure is foo:(Seq)String
def foo(xs : Int*) = 3; // after erasure is foo:(Seq)Int
}
You might want to look at this question about the signature of map
which has a parametric return type That
. Martin Odersky's answer explains how (and why) different types may be returned.
Note that the return type is not bound in any way to Traversable
, or even the parametrized type of the target. For example:
IndexedSeq[Char].map --> String
As can be seen by looking at StringOps
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