In Scala v2.9.2 (and 2.8.0), this script:
case class MyString(s: String)
implicit def stringToMyString(s: String) = MyString(s)
implicit val defaults: Map[String, MyString] = Map("abc" -> MyString("123"))
case class HasDefaults(name: String = "none",
baseMap: Map[String, MyString] = Map.empty) {
def add(kvp: (String, MyString)*)(implicit defaults: Map[String, MyString]) =
this.copy(baseMap = this.baseMap ++ defaults ++ kvp)
}
val hasDefaults = HasDefaults() add (
"def" -> "124",
"xyz" -> MyString("999")
)
println(hasDefaults)
Fails with:
java.util.NoSuchElementException: key not found: 124
at scala.collection.MapLike$class.default(MapLike.scala:224)
at scala.collection.immutable.Map$Map1.default(Map.scala:106)
at scala.collection.MapLike$class.apply(MapLike.scala:135)
at scala.collection.immutable.Map$Map1.apply(Map.scala:106)
at Main$$anon$1.<init>(HasDefaults.scala:12)
It is trying to use the String value "124" as a key in a map lookup, even though it is defined as a value (by virtue of being on the right hand side of the -> operator).
Note, this error goes away if the implicit conversion to MyString is not attempted. e.g.:
val hasDefaults = HasDefaults().add(
"def" -> MyString("124"),
"xyz" -> MyString("999")
)
Note #2, the error also goes away if the implicit parameter is provided explicitly. e.g.:
val hasDefaults = HasDefaults().add(
"def" -> "124",
"xyz" -> MyString("999")
)(Map("abc" -> MyString("123")))
In Scala,
Mapis a function. (Map[A, B] <: PartialFunction[A, B] <: A => B.) Sodefaultsacts like an implicit conversion fromStringtoMyString. Sincedefaultsdoes not contain"124", you get a “key not found” error.