So, we learn that using get is bad: a code smell. Idiomatic Scala recommends using pattern matching or monadic operations like map, flatMap, etc. for working with values from such containers.
So, if get is so bad, then why is Map[K,V] designed the way it is? Map[K,V] extends GenMapLike[K,V], which actually defines the following two methods:
- abstract def apply(key: K): V
- abstract def get(key: K): Option[V]
Thus, effectively, GenMapLike[K,V] extends Function1[K,V]. This class was originally written by Martin Odersky, although not until 2.9. I'm assuming that it was written this way to be compatible with earlier versions. In Scala 2.8, MapLike[K,V] extends Function1[K,V] via PartialFunction[K,V]. Again, Odersky was the author.
If the value of key is unknown in the map, the so-called default method is invoked. By default, the default method simply throws an exception (as you'd expect). In other words, apply is the dangerous method (default notwithstanding) and get is the safe method.
So, is it just me, or are these definitions backwards? This is how I feel that the methods in GenMapLike[K,V] should be defined:
- abstract def get(key: K): V
- abstract def apply(key: K): Option[V]
Thus, GenMapLike[K,V] would effectively extend Function1[K,Option[V]]. What would be wrong with that? It would be so much more consistent. By all means have this version of get invoke the default mechanism. But it would still essentially correspond to the dangerous method.
Obviously, nobody is going to change it now. And, they're just names, right? But it does seem a shame that it got this way in the first place.
I agree. I've had to make a mental note that `Map.get(key: K)` doesn't mean "throw if not found". It would have been better to go about this from the beginning in the way that you state, but it's too late now.
ReplyDeleteMaybe it was done this way because way back in the early days of Scala `.get()` didn't have the stigma it has now, but that's just a guess.