The Scala programming language: My First Impressions
I keep coming across praise for a new programming language called Scala. I looked into it a bit, and here are my first impressions. I have not written any programs in it, so I am hardly even a beginner, let along an expert. My own opinions are in parentheses. Please comment on this post to correct my errors.
I started with the JavaPolis ’07 interview with Martin Odersky. (He’s the kind of person I like: clear, cogent, practical, charming, and modest.) I then downloaded it.
History: The key inventor is Martin Odersky, who heads the programming research group at Ecole Polytechnique Federale de Lausanne as a full professor, and was one of the designers of Java generics. He was a student of Wirth and came from the Modula-2 tradition, but later got interested in functional programming, and is now associate editor of the Journal of Functional Programming. He’s been working on Scala for over five years. He originally used Scala in classes, teaching Java first, and then Scala in the next year as a “power Java”. The first public release was in 2004, and he revised it substantially in 2006. There has been a series of versions, maintained with back-compatibility and a deprecation protocol. The current version is 2.6.
What’s it for?: It is intended to be a general-purpose language that could replace Java. So far it has primarily been used for web-related applications. The first industrial users were a company called Sygneca in the U.K., who have used to build web sites for agencies of the British government. Perhaps the best-known development has been David Pollack’s Liftweb, a web framework along the lines of Rails, which is getting a lot of attention and has many committers. See .
Documentation: Odersky recommends starting with “First Steps To Scala” (also in the distribution). Then, you can move on to the book “Programming in Scala”, by himself and others, which just came out on Dec 12 (two weeks ago, as I write this). You can get the PDF for US$22.50. It assumes you know Java. The distribution comes with a reference manual.
Functional programming: Scala is intended to be a fusion of functional programming and object-oriented programming, rather than a “pure” function language like Haskell or ML. Ordinary imperative programming works fine. Objects can be mutable or immutable. The latter is preferred when it’s possible, since it needs no concurrency control. Also, these days it’s faster to make new objects and allow them to be efficiently GC’ed, than incur the GC overhead that results when you mutate an existing object (interesting point!). There are mutable arrays, but immutable (parameterized) List objects. (I am entertained that the infix operator “::”, which makes a new List with an element prepended, is pronounced “cons”!) “Nil” creates an empty list (unlike Lisp, lists are first-class). The lexeme “=>” is used to define anonymous functions (what Lisp people call lambda expressions), so you can do mylist.filter(s => s.length = 4). There are also immutable “tuples” whose elements can be of any type and which have a very simple creation syntax: (52, “Locust”). (These are even more like Lisp lists). One thing you’d use this for is multiple-value return.
Object-oriented programming: Notice how few explicit type declarations there are:
class SimpleGreeter {
val greeting = "Hello, world!"
def greet() = println(greeting)
}
val g = new SimpleGreeter
g.greet()
There are no static fields or methods. Instead, you use singletons. The concept of singletons is built into the language, so the syntax is concise and stylized. (I’ve said before that the famous “Design Patterns” are often just conventions that make up for things that the language cannot do itself. Here’s another example of a pattern that’s no longer needed as a pattern.) There are “traits”, which are like Java interfaces except that they can define default method implementations. Although Scala is “single inheritance of implementation” like Java, there’s a way to use traits that provides a simple “mixin” facility.
Interpreter: Scala has an interactive interpreter (what Lisp people call a “read-eval-print loop”) (right there, we’re way ahead of Java!). You can define variables without specifying the type; it infers it. Here’s a simple function definition:
def max(x: Int, y: Int): Int = if (x < y) y else x
Parameter types are not inferred, so they must be specified. But in some cases, including this one, the result type is inferred.
Concurrency: There is a library trait called “Actor”. It’s based on the concepts in this paper and this paper, which I have not yet read. It looks like it’s oriented around asynchronous messaging.
Sharing of libraries: There is a system called Scala Bazaars, or “sbaz”, to help the open source community share libraries. There appear to be around 250 contributions already.
Some other interesting features: The syntax of XML is embedded in Scala. There are primitives for pattern matching (what Lisp people would call destructuring). There are user-defined annotations.
Implementation: The main Scala compiler produces Java class files; It can operate seamlessly with Java. (This means you get an excellent JIT compiler, an excellent GC, and lots of libraries, a huge plus for a new language.) There’s also a compiler that makes binaries for the .NET CLR.
Interactive development environments: It comes with GNU Emacs support, and there are plugins available for Eclipse and IntelliJ IDEA.
Persistence: It works with the db40 object-oriented database system.
Summary: I feel that the way functional, object-oriented, and imperative programming are combined in Scala is much like the way they are combined in Lisp. As compared to Lisp:
- conventional syntax; more approachable to many people
- no Lisp-like macros
- much cleaner (anything is cleaner than Common Lisp, of course)
- statically typed with inferencing: the best of static typing without the worst parts
- no ability to incrementally recompile and re-run (as far as I can see)
The emphasis on immutability and the Actor class also makes me think of Erlang, but I know too little about both Scala and Erlang to venture further comments.
It looks extremely promising. I’ll be keeping an eye on this.
December 25th, 2007 at 8:26 pm
I’ve been trying out Scala for the past 2 weeks in various small projects to get the grip of it. It has many many nice features, which is both an advantage (the features are NICE : OO + FP + all the java goodies but with a better language) and an disadvantage (there are MANY features which means it’s hard for a newcomer to keep them all in mind and makes it a language on the scale of C++/Java/C# to learn even for people with experience in functional programming + it has some of the verbosity of its direct ancestor)
That said, I’d rather choose it over its older sibling(s) any time (even though, or maybe because, I have more experience with them and know what pains they can be)
December 25th, 2007 at 8:42 pm
Interestingly, in Scala lists aren’t “first-class” at all. They’re not even syntactic sugar; their clear syntax flows freely from the language’s grammar. Here are some forms:
val mylist = 3 :: 4 :: NilIn this case, :: is resolved to a method in scala.List. In this case the only “magic”, apart from the fact that Scala allows methods (and classes) named “::”, is that any method (including an “operator”) that ends in colon is right-associative. i.e. read this line as
Nil.cons(4.cons(3)).Nilis the singleton empty list object.val myOtherList = List(3,4)In this case we’re using the
applyfunction in the singletonListobject. The Scala compiler will search for anapplymethod any time an instance or an object is found where a function call would be expected.December 25th, 2007 at 9:21 pm
Excellent review. I’m working through the PDF and and am enjoying my journey.
I think we have a different idea of what “clean” is, because I’d hardly say that “…anything is cleaner than CL…”. How do you figure? What makes CL “dirtier” than Scala (or anything else)?
Also, while I know it’s all the rage (again), and probably the default for your blogging software, I find the full text justification just as ugly now as I did when I first saw it on a 9 pin dot matrix printer using Scripsit on the TRS-80. Yuck.
Michael
December 25th, 2007 at 10:03 pm
Hmm doesnt have these languages offer some that is REALLY unique?
I mean… scala looks a bit like an overly verbose python, what is the difference?
December 25th, 2007 at 10:17 pm
ML is not a pure functional language. You should fix it.
I’ve never looked close Scala but I have hopes on it
December 25th, 2007 at 11:53 pm
JavaRebel allows you to hot swap running code.
The Actor library is indeed inspired by Erlang.
Scala is also fully interoperable with Java libraries.
December 26th, 2007 at 5:44 am
This looks a little like Ruby with optional types. Even the example Greeter Class example you show I literally just saw on ruby-lang.org’s front page. Maybe that is a common example though.
I have heard a little about this but I don’t remember where it was from. Nice little article.
December 26th, 2007 at 7:05 am
The company to which you refer is Sygneca Ltd. … see http://www.sygneca.com/ or the Scala Wiki that they host, at http://scala.sygneca.com/ .
Thanks for the nice, concise and unemotional summary of the current state of this interesting language.
December 26th, 2007 at 1:40 pm
Alex: In Common Lisp, I have always felt that lists are not a first-class datatype, by which I mean that it’s harder to manipulate them than it ought to be. You can’t say “Here is a list. Add this object to the head of the list, as a side-effect,” as if there were some list object that could be modified. See Jeremy Brown’s posting on this subject. Thanks for the explanation of exactly what is special about the syntax, and the way apply is invoked. I hadn’t understood that from what I had read.
Michael Campbell: Common Lisp has a lot of irregularity. I discuss this in my later post. Of course, I’m a huge Common Lisp fan and booster, but it’s important to be honest about its pros and cons.
she: The most fundamental difference I see between Scala and Python is that Scala has typed variables, with type inferencing, whereas Python has untyped variables.
Diego: I am woefully ignorant about ML. Odersky, in his interview, described it as a “pure” functional language, although I don’t know whether he intending to use that word in a very technical sense or a more colloquial sense.
Jorge: I’ve never heard of JavaRebel; I’ll look into that. The last time I was heavily involved in Java (at BEA Systems), hot swapping for Java itself was either here or almost here. You can definitely hot swap in BEA’s Java implementation, known as JRockit. (If you use Java, definitely check out JRockit, which is a very fast implementation with some nice tools and a great GC. It’s free.)
December 27th, 2007 at 3:37 am
ML is definitely not a pure functional language. In fact it’s very clear that it intends to be a multiple-paradigm language. To be honest, the hair of supporting a primarily functional and strictly-typed language (with type inference), has always kept me from quite coming to grips with it. I’ve been using Lisp too long; I was on the plane teaching myself Ocaml (a variant), and I kept finding myself thinking, “yuck! syntax!” I think this actually has to do with my discomfort about the particular decisions they made in choosing syntax for pattern-matching and generic typing, and doing all that horrible currying…. I don’t know why they think they’re doing me a favor by turning my n-ary function into a curried mess of functions that return functions. I mean, I know it could be down there, but I wish they’d stop typing it at me!
December 28th, 2007 at 3:48 pm
You write:
What is the GC overhead from mutation? Perhaps you refer to the synchronization overhead? Apologies for the ignorant question.
Andy
December 28th, 2007 at 10:24 pm
Interesting post and comments. Scala is indeed looking very good, even better now than when I first found it a year or so ago. I’ve got some further comments.
Regarding purity, it depends on how we define it, of course. I believe that Odersky is well aware that ML is not “purely functional” in the sense of being “referentially transparent”, because it allows functions with “hidden” side-effects that aren’t transparent. But I don’t think ML was ever conceived as a multi-paradigm language (not the original ML, at least; OCaml is another matter). ML is primarily functional, with side-effects allowed for pragmatic reasons, but a side-effects-free programming style is preferred.
As for differences with python, there are many. I, and many others that have worked with scala for some time, think of it like a mix of Java and Haskell. Scala is statically-typed with type inference, favors a functional style, runs in the Java Virtual Machine and its type system would appear very strange for a python programming, I guess.
December 28th, 2007 at 10:41 pm
Also, in ML you actually can choose if you want a curried function or not. In OCaml syntax:
fun x y -> x + y has type int -> int -> int, curried;
fun (x, y) -> x + y has type int * int -> int, the single argument is a tuple, so this function can’t be curried.
December 29th, 2007 at 12:37 am
The eclipse plugin supports incremental compilation, and when combined with the JVM’s support for hot swapping, you can edit your program while its running. This is given the limitations of the JVM: if you add a new method or class, your debugging session has to be restarted. Unfortunately, this includes closures (which compile down to JVM classes). Hopefully Sun will fix this when they add closures to Java.
December 29th, 2007 at 9:43 am
ML is a family of impure functional programming languages of which OCaml is the most popular with ~100x as many users as Scala.
December 29th, 2007 at 10:09 am
@dlweinreb
“class” definitions have to be instantiated, like in Java. “object” definitions are singletons (they only contain static members):
object SimpleGreeter {
private val greeting = “Hello, world!”
def greet = println(greeting)
}
SimpleGreeter.greet
Note that the parentheses after method calls are optional. By convention, Scala programmers write them if the method call has side effects, and leave them out otherwise (for example a getter has no parentheses).
In your example of “max”, the result type (Int) is explicitly mentioned, the example code should probably read:
def max(x: Int, y: Int) = if (x < y) y else x
Variable types of arguments have to be explicitly mentioned, because they cannot be “guessed” from the context.
Traits are like abstract classes or interfaces, with the exception that they have no constructors. This allows Scala to do multiple inheritance. Traits are described here: http://www.iam.unibe.ch/~scg/Research/Traits/
Thanks for the review! By the way, I was a student of Martin Odersky’s course of “Power Java”. One of our assignments was to write a simple LISP interpreter in Scala (with REPL). You might be interested:
http://lampwww.epfl.ch/teaching/archive/programmation_4/2007/exercises/project6/project6.pdf
http://lampwww.epfl.ch/teaching/archive/programmation_4/2007/exercises/project6/lisp-partial.scala
December 30th, 2007 at 1:45 pm
Andy: If you mutate an existing object, and the object has been tenured, that can cause a crossing of the “write barrier”, as the GC has to worry that maybe you are storing a pointer from tenured (old object) space to the new object space and thus making the new object non-garbage. (Actually it’s been so long since I was up on this stuff that I’m not sure I’m right about how this works, so if you really need to know, I suggest that you read up on generational GC algorithms rather than take my word for it.)
December 31st, 2007 at 5:47 pm
Nice review Dan. Berkeley DB Java Edition also works with Scala. See this OTN post for details.
http://forums.oracle.com/forums/thread.jspa?threadID=594269&tstart=15
-cwl
January 10th, 2008 at 10:25 pm
[...] I think I’ll do what Dan Weinreb’s going to do and just keep an eye on Scala to see what happens next. Now, since he is way smarter [...]