(descending in severity, IMO)
Scala exposes runtime implementation details to users! See the pitfalls around catching Throwable: http://www.tzavellas.com/techblog/2010/09/20/catching-throwable-in-scala/
https://issues.scala-lang.org/browse/SI-8899
http://www.youtube.com/watch?v=uiJycy6dFSQ
e.g.
scala> Set(1) == Set(1L)
res0: Boolean = true
scala> TreeSet(1) == TreeSet(1L)
res1: Boolean = false // what?!
https://issues.scala-lang.org/browse/SI-8876
Suppose I have this case class:
scala> case class C(i: Int, implicit val s: String)
defined class C
scala> C(1,"")
res0: C = C(1,)
Now I decide I want 'i' to be implicit...
scala> case class C(implicit i: Int, val s: String)
defined class C
scala> C(1,"")
<console>:10: error: too many arguments for method apply: ()(implicit i: Int, implicit s: String)C in object C
C(1,"")
C(1, "")
no longer compiles! Instead, the caller has to change:
scala> C()(1,"")
res2: C = C(1,)
Breaking callers is very unfortunate...
Arguments in anonymous functions can not be destructured. Instead, you have to use a different syntax:
List((1,"a"),(2,"b"),(3,"c")).map(i => i+1) // works
List((1,"a"),(2,"b"),(3,"c")).map((i,a) => i) // fails to compile!
List((1,"a"),(2,"b"),(3,"c")).map { case (i,a) => i } // what I have to do instead
Haskell does this well. Java does not support destructing at all.
val s : Option[String] = Some("foo")
s getOrElse "Chocolate"
s getOrElse null // has type String (yay)
val b : Option[Boolean] = Some(true)
b getOrElse false
b getOrElse null // has type Any (nooo, I wanted Boolean)
See https://code.google.com/p/guava-libraries/issues/detail?id=1095 , which leads to hard-to-diagnose issues.
Not distinguishing between call-site being able to use implicit resolution, and the implementation wanting to use implicit.
I want a constructor argument to be implicitly available in my instance, but not for the caller to be able to construct using implicitly available instance. Scala does not distinguish between these needs, and instead implicitness is propogated whenever it is passed in constructors.
https://issues.scala-lang.org/browse/SI-4389
val a = 1
val A = 1
val (b,c) = (2,3)
val (B,C) = (2,3) // does not compile
This is because you can have uppercase variables, but can not destructure to upper case variable (since it s treated as an extractor)
mvn chooses version closest to root. sbt chooses latest version. This could cause bugs.
This is not a Scala language issue, but is a Scala ecosystem issue. When choosing a language, you are which is likely what you are really interested in.