Scala maps -> operator
Solution 1
The ->
operator is a shorthand for associating a key with a value when used in the context of a map. In some languages, you are simply allowed to pass the pair of the key and value (usually with the key in the first position and the value in the second) to the constructor or one of the various methods on a map and it will be handled appropriately -- this is also allowed with Scala maps.
However, Scala also provides the shorthand form of key -> value
, which, as you've discovered, is defined in Predef via an implicit, to make the association more clear. Essentially it's saying: "take the item on the left and map it to the item on the right." You'll notice if you read the definition of the Map object, that it does not define any methods that obviously use this ->
method. Instead, the methods take objects of type Tuple2
(this is a tuple of 2 values: e.g. (item1, item2)
), which Scala implicity converts via the method in Predef.
In some languages, the ->
syntax is defined as part of the language itself, but due to the flexibility of Scala, this is able to be defined simply as a method.
Solution 2
Here's the implicit conversion:
implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
This will convert any type into an instance of "ArrowAssoc"
class ArrowAssoc[A](x: A) {
def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
}
So when Scala sees
"a"->1
It says "There is no method named '->' on String. Are there any implicit conversions in scope that can give me a type that has a method named '->'?" Predef.scala is automatically in scope, and offers a conversion to ArrowAssoc, which obviously has the '->' method. Scala then essentially converts the above to
any2ArrowAssoc("a").->(1)
This method returns a Tuple2("a", 1) (often called a Pair). Map has a constructor that thats an array (varargs) of Tuple2s, so we're off to races! No magic in the compiler (besides implicit conversion, which is used extensively and for many different purposes), and no magic in Maps constructor.
Solution 3
->
is used to couple keys and values for a map. So:
val m = Map(1 -> "one", 2 -> "two", 3 -> "three")
will map the first 3 positive integers into text equivalents (that is, m(1)
will be "one"
, etc.). You could also write it as
val m = Map((1,"one"), (2,"two"), (3,"three"))
but the first way looks nicer, which is why it's provided as an alternative.
Solution 4
As Adam said, ->
is not scala syntax, it is a method of the class ArrowAssoc
. When you write "foo" -> "bar", the compiler inserts a implicit conversion from "foo" to ArrowAssoc instance so that the ->
method can be found.
package scala
object Predef {
class ArrowAssoc[A](x: A) {
def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
}
implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] =
new ArrowAssoc(x)
...
}
google "“scala rich wrappers” to know more.
Kamil
Updated on July 09, 2022Comments
-
Kamil almost 2 years
What does the symbol
->
mean in the context of aMap
in Scala?Scala’s
Predef
class offers an implicit conversion that lets one writekey -> value
as an alternate syntax for the pair(key, value)
. I read it in ScalaByExample but fail to see how this works for Maps. -
Kamil about 13 yearsyeah :D but you only write a example of that what i wrote. But i need to know how explain meening of this operator
-
denis phillips about 13 yearsMore precisely, key->value creates a tuple (key,value). The Map object's apply method takes a variable number of tuples of the form (A,B) which are used to create the map.
-
Rex Kerr about 13 years@Kamil - I didn't understand what was not clear to you. I'm glad you found Thomas' answer useful.
-
Thomas Lockney about 13 yearsThanks. David, I was thinking it was using the Pair type in Predef -- having just reread that code, I should have remembered. I'll edit my answer to correct that.
-
jayunit100 almost 10 yearsThis is a superb explanation of how scala implicits work to build up primitives in the language
-
TriCore over 6 yearsthe first way may be nicer but having two different ways to do same thing certainly confused me (and apparently others too) . Thanks for your explanation!
-
TriCore over 6 yearsa lot of text :)
-
Charlie 木匠 almost 5 yearsSeems it can explain this, it's not a Map, but a Tuple: val buildings = Array(Array(2,3,5), Array(1,8,2)); val keyPoints = buildings.map(b => List(b(0)->b(2), b(1)->b(2)));