Scala maps -> operator

26,140

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.

Share:
26,140
Kamil
Author by

Kamil

Updated on July 09, 2022

Comments

  • Kamil
    Kamil almost 2 years

    What does the symbol -> mean in the context of a Map in Scala?

    Scala’s Predef class offers an implicit conversion that lets one write key -> 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
    Kamil about 13 years
    yeah :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
    denis phillips about 13 years
    More 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
    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
    Thomas Lockney about 13 years
    Thanks. 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
    jayunit100 almost 10 years
    This is a superb explanation of how scala implicits work to build up primitives in the language
  • TriCore
    TriCore over 6 years
    the 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
    TriCore over 6 years
    a lot of text :)
  • Charlie 木匠
    Charlie 木匠 almost 5 years
    Seems 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)));