First impressions of Scala
I don’t want to write raw Java again, but I need to write ImageJ plugins. I’m on the hunt for a new language.
Almost a year ago, I wrote an interface between Kawa and ImageJ, but ImageJ’s design precludes giving Kawa the type annotations it needs to make the interface reasonably fast.
I am no longer appalled by languages like Java. They are muck heaps. The last good language in this family was ALGOL 68. I am appalled by Scala. It tries to be a modern language while still poking its tendrils into the muck heap, but managing the muck has contaminated the language.
Certain things tell me I have been in Haskell too long. I am mildly disturbed by assigning types as values. The case classes, which try to be algebraic data types, miss the point, since you can’t check if functions over them are total.
The primary horrors:
Covariant/contravariant types: Java isn’t strongly typed. You can cast a String to an Object, assign it an integer, and the compiler cannot tell. To escape this, Scala introduces covariant/contravariant types.
Consider the function cons :: a -> [a] -> [a]. The first argument can be any subclass of a. We call it "covariant." The second argument, any superclass of a works in the list. It is "contravariant."
The best solution is to remove inheritance entirely, but the muck monster won’t talk to anyone without inheritance.
Implicit parameters: A library call returns a list. You want to use it as a set, which you have set up as a subclass of list. Write a function which converts lists to sets, annotate it with the implicit keyword, and then you can happily treat the library’s return value as a set.
There are two uses for this. One lets you create typeclasses by defining "traits" (Java interfaces with arbitrary restrictions removed) and then implicitly coercing everything you want into this trait. The other lets you add fields and methods to existing classes and objects.
In the first use, the only claim the creators advance for this approach instead of typeclasses is that implicit parameters are scoped. I learned my lesson about implicit things when I had to maintain a large Perl code base, but this makes the implicit conversions in Perl look like child’s play.
The second use is ludicrous. In Smalltalk, if I want to extend a predefined class C with a method f, I just assign the function body to the field f of C. I can only use the public interface of C, so it isn’t dangerous.
Henry Ware:
Scala’s case classes do detect total functions in the cases where it is possible to do so:
sealed abstract class Foo{}
case class Left extends Foo{}
case class Right extends Foo{}
def left(foo:Foo)=foo match{
case l:Left => 2
}
Quick.scala:7: warning: match is not exhaustive
This does not work for non-sealed classes– where additional cases may not be known at compile time– or for cases where unapply is used.
5 November 2007, 6:12 pmmadhadron:
Thanks for pointing that out. I hadn’t noticed it in the documentation.
6 November 2007, 2:38 pm