Reputation: 16143
C:\Users\John>scala
Welcome to Scala version 2.9.2 (Java HotSpot(TM) Client VM, Java 1.6.0_32).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map
scala> Map()
res4: scala.collection.mutable.Map[Nothing,Nothing] = Map()
When using Map()
without keyword new
the apply
method from the corresponding companion object will be called. But the Scala Documentation does not list an apply
method for mutable Maps (only an apply
method to retrieve a value from the map is provided).
Why is the code above still working ?
Upvotes: 3
Views: 349
Reputation: 53348
As sepp2k
already mentioned in his comment the symbol Map
refers to the companion object of Map
, which gives you access to its single instance. In patter-matching this is often used to identify a message:
scala> case object Foo
defined module Foo
scala> def send[A](a: A) = a match { case Foo => "got a Foo" case Map => "got a Map" }
send: [A](a: A)String
scala> send(Map)
res8: String = got a Map
scala> send(Foo)
res9: String = got a Foo
If you write Map()
you will call the apply
method of object Map
. Because you did not give any values to insert into the Map
the compiler can't infer any type, thus it has to use the bottom type - Nothing
- which is a subtype of every type. It is the only possible type to infer which will not break the type system although there are variances. Would Nothing
not exist the following code would not compile:
scala> Map(1 -> 1) ++ Map()
res10: scala.collection.mutable.Map[Int,Int] = Map(1 -> 1)
If you take a look to the type signature of ++
which is as follows (source)
def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1]
you will notice the lower-bound type parameter B1 >: B
. Because Nothing
is a subtype of everything (and B
in our case) the compiler can find a B1
(which is Int
in our case) and successfully infer a type signature for our Map. This lower-bound is needed because B
is covariant (source),
trait MapLike[A, +B, ...] ...
which means that we are not allowed to deliver it as a method parameter (because method parameters are in contravariant position). If the method parameters would not be in contravariant position Liskov's substitution principle would no longer kept by the type system. Thus to get the code to compile a new type (here called B1
) has to be found.
As Didier Dupont
already pointed out there are some bugs in Scaladoc 2.9, which are solved in 2.10. Not only some missed methods are displayed there but also methods added by an implicit conversion can be displayed (Array for example does display a lot of methods in 2.10 which are not displayed in 2.9).
Upvotes: 1
Reputation: 20515
There is an apply() method on the companion object of scala.collection.immutable.Map()
. It is inherited from scala.collection.MapFactory
. That method takes a variable number of pair arguments, and is usually used as
Map("foo"->3, "bar"->4, "barangus"->5)
Calling it with no arguments evidently works as well, but someone brighter than me would have to explain why the type inference engine comes up with scala.collection.mutable.Map[Nothing,Nothing]
for it.
Upvotes: 3
Reputation: 29528
It looks like a bug in scaladoc. There is an apply
method in object collection.mutable.Map
(inherited from GenMapFactory
) but it does not appear in the doc for Map. This problem seems to be fixed in the doc for upcomping 2.10.
Note : you must look into the object documentation, not the class one. The method apply
in the class
of course works with an existing map instance, and retrieve data from it.
Upvotes: 5