I find that Scala is one giant Rube Goldberg Machine that manages to do something not easily be done otherwise. By this I mean that Scala has many features that, by themselves, seem very strange, but, in combination, enable some very cool functionality. This is why I initially started my personal tour of Scala. I read stuff like explicitly typed self-references and was left scratching my head.
I thought it might be fun to deconstruct the "map literal" in Scala and observie how the features interact to create a very handy piece of code that isn't baked into the language. This assumes and understanding of some Scala basics.
Although Java 7 is getting map literals, Scala already has it (or so it appears):
val band = Map("Dave" -> "Bass", "Tony" -> "Guitar", "Greg" -> "Drums")
Most surprising to a Java programmer is the -> operator. This makes use of two Scala features:
It turns out that the -> operator is on the class Predef.ArrowAssoc. Predef is automatically imported in every Scala program, so you don't need to prefix anything with Predef. It returns a tuple of its caller and its argument, e.g.
val dave = new ArrowAssoc("Dave") val entry = dave -> "Bass" // entry is now ("Dave","Bass") // which is a Tuple2[String,String]
Of course, we aren't creating ArrowAssoc instances anywhere, so how does this get called? This is where implicits come in. Suppose we change our simple example to:
val dave = "Dave" val entry = dave -> "Bass" // entry is still ("Dave","Bass") // which is a Tuple2[String,String]
implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
This means our code is now effectively:
val band = Map(("Dave" , "Bass"), ("Tony" , "Guitar"), ("Greg" , "Drums"))
This use two additional Scala features:
val band = Map.apply(("Dave" , "Bass"), ("Tony" , "Guitar"), ("Greg" , "Drums"))
That's all there is to it! A few things to note about this:
- Without the application of some Scala features, it's pretty ugly
- The language itself didn't need to implement a special "map literal"; it simply combines smaller features in a way to make it appear as though it does. You can even create your own "literals" rather than waiting for the language to implement them