Reputation: 5702
I am very confused about why Scala doesn't allow things that it should be able to infer. If I want to store arbitrary types in a Map I imagine this should be possible but am blocked where there seems to be enough information to perform the operation.
scala> var m: Map[Any, Any] = Map()
m: Map[Any,Any] = Map()
scala> m = ("one" -> 1, 2 -> "two", 3 -> 3)
<console>:8: error: type mismatch;
found : ((String, Int), (Int, String), (Int, Int))
required: Map[Any,Any]
m = ("one" -> 1, 2 -> "two", 3 -> 3)
^
scala> m += ("one" -> 1)
scala> m += (2 -> "two")
scala> m += (3 -> 3)
scala> m
res25: Map[Any,Any] = Map(one -> 1, 2 -> two, 3 -> 3)
scala> m("one").getClass
res26: Class[_] = class java.lang.Integer
scala> m(3).getClass
res27: Class[_] = class java.lang.Integer
scala> val result = m("one")+m(3)
<console>:8: error: type mismatch;
found : Any
required: String
val result = m("one")+m(3)
^
scala> val result: Int = m("one")+m(3)
<console>:8: error: type mismatch;
found : Any
required: String
val result: Int = m("one")+m(3)
^
scala> val mr1 = m("one")
mr1: Any = 1
scala> val mr1 = m("one") => Int
<console>:1: error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
Either create a single parameter accepting the Tuple1,
or consider a pattern matching anonymous function: `{ case (param1, param1) => ... }
val mr1 = m("one") => Int
^
Ultimately I do know the type of the Key (String), and since the value's real types are known, I should be at least able to cast them, right? I also realize the code has to be type safe.
I'm clearly doing trial and mostly error here, can anyone offer guidance.
Upvotes: 0
Views: 1011
Reputation: 52701
This is wrong:
m = ("one" -> 1, 2 -> "two", 3 -> 3)
You are trying to assign a Tuple3
to m
, which you declared as a Map[Any,Any]
. You meant:
m = Map("one" -> 1, 2 -> "two", 3 -> 3)
However, it's worth noting that a having things of type Any
in your code is almost certainly a bad idea. Type-safety is great and is one of the major benefits of using Scala. You should take advantage of it.
Upvotes: 3
Reputation: 144206
In
m = ("one" -> 1, 2 -> "two", 3 -> 3)
you are trying to assign to m
so the right-hand side must be compatible with Map[Any, Any]
. However, ("one" -> 1, 2 -> "two", 3 -> 3)
is a tuple which is not compatible, hence the error.
In
m += ("one" -> 1)
you are calling the +
method of Map[Any, Any]
with a Tuple2[Any, Any]
argument. While ("one" -> 1)
has type (String, Int)
this is compatible with (Any, Any)
so they can be added individually.
Note you can also do:
m += ("one" -> 1, 2 -> "two", 3 -> 3)
When you lookup elements in the map, the type of the return value is Any
, so the types of m("one")
and m(3)
are both Any
. Since Any
has no +
operator, m("one")+m(3)
will not compile. If you know both values are Int
s then you can cast them:
m("one").asInstanceOf[Int] +m(3).asInstanceOf[Int]
Upvotes: 3