Friday, November 21, 2008

Scala?

I received a free copy of the Scala eBook by Martin Odersky, Lex Spoon, and Bill Venners. I tried to read it on my CalTrain commute, but ended up only skimming -- at 700+ pages it's a hefty tome. I'm also not in the primary target audience, as its focus seems to bounce between trying to entice Java programmers to try a better language, and an introduction to programming that happens to use Scala. I ended up going to the Scala website where I downloaded various other documents, such as a tutorial, a more technical overview paper, and the language reference.

Sad to say, I'm quite disappointed (in the language -- can't really say much about the quality of the eBook except that it's as big as the language). One of the first times I heard Scala mentioned it was a talk by Steve Yegge at Google I/O last May. Steve characterized Scala as "static typic's revenge" (I'm paraphrasing -- too lazy to watch the video to find that section) and went on to make fun of the incredible complexity of Scala's type system, which contains such esoteric concepts as type erasures, variance annotations, existential types, polymorphic method types, and many more (just scan the ToC of the language reference).

I have to agree with Steve -- if this is what it takes to have compile-time type-safety in a language, I'll take dynamic typing any day. There's got to be a better way -- perhaps Haskell? Haskell is a pure functional language with a fast implementation that seems to have solved the I/O problem of functional languages well -- while its Monads are truly deep and take real work to create, their use seems quite straightforeward.

Perhaps my biggest disappointment in Scala is that they have so many rules to make it possible to write code that looks straightforward, while being anything but -- these rules all seem to have innumerable exceptions, making it hard to know when writing simple code will work and when not. For example, the Scala book explains that you can use multiple 'if' qualifiers in its for-statement, but points out that you have to insert a semicolon in a position where you'd expect it to be inferred by the parser. To make matters even more mysterious, if you were to use curly braces instead of parentheses, you can omit the semicolon. All this is presented without any explanation. I found the explanation by combining two seemingly unrelated rules in the reference manual: first, the for-statement (technically called for-comprehension) allows both braces or parentheses with exactly the same semantics, but the rules for inferring semicolons are different inside braces than they are inside parentheses. Obvious, eh! :-)

33 comments:

Ian Bicking said...

My own thoughts on typing are perhaps similar -- it's not that dynamic typing is right, it's just doable. People will often say "oh, but static typing is doable! You just haven't looked at language X"... but then when you look closely (as you did with Scala) it's not simple at all.

Or Haskell... I finally figured out Monads, which seemed so magical and powerful in the abstract, and then all I could think was: they go through all this trouble just to handle errors and null?

I'm sure there's something new and exciting yet to be discovered in languages; there's got to be some point when I'll tell myself it's time to move on to something new and better. I just don't believe it will have anything to do with types.

Guido van Rossum said...

It may not have to do with types in the current sense, but it will most likely involve more compile-time checking for potential errors. Types are just the primary focus of compile-time checking at the moment.

The cynic in me says that this is at least in part due to a long-standing academic interest in types, which makes it easy to get papers about novel type checking approaches to get accepted than papers about other topics related to compile-time checking.

Paul Snively said...

I don't know that Scala is what it takes to have static typing; it might be what it takes to have a very expressive static type system in a language that nevertheless runs on the JVM and is able to call Java libraries transparently. In any case, I do agree that it can be usefully compared with Haskell if you strive to keep in mind Scala and Haskell's differing objectives.

To Ian I would only say that monads aren't just for failure continuations and Maybe. :-)

I'll also disagree with Ian that new and better won't have anything to do with types: it almost certainly will, I believe, because the big outstanding challenges, security and concurrency, are better addressed by static type systems than by their absence (citations upon request).

Guido van Rossum said...

"what it takes to have a very expressive static type system in a language that nevertheless runs on the JVM and is able to call Java libraries transparently."

Maybe so, but I think the poor programmer isn't served by all this complexity. So maybe the goal is wrong. Sort of like C++ became too complex for the average developer by having as an explicit goal backwards compatibility (with C no less) and the ability to get as close to the hardware as possible.

Dan Shoutis said...

I've been using Scala fairly intensively lately, and the huge syntax is probably its biggest weakness.

They type system takes some getting used to ... but, for me, it has a huge advantage that you don't normally see with static types: it is an incredibly powerful way to perform metaprogramming.

I could actually care less about the checking (well, it's nice), but type inference + function overloading + implicits is a very powerful combination for managing overly complicated 3rd-party APIs, and brainy symbolic algorithms (the latter is also Haskell's sweet spot).

Ricky Clarkson said...

I usually look to the language spec when learning a new language. C#'s was amazingly well-written, if a bit verbose in places. Scala's was really really hard to follow. The book you refer to wasn't around at the time. I persevered though, and found that I didn't really need to learn very much to get started with Scala, though I have learned a number of the other concepts as I've gone along.

It's a good language, but one I hope can carry on evolving, because as you pointed out, it's full of hysterical raisins. As a user you can easily ignore most of them, and importantly, they are rarely runtime gotchas.

Paul Snively said...

Guido van Rossum: It may not have to do with types in the current sense, but it will most likely involve more compile-time checking for potential errors. Types are just the primary focus of compile-time checking at the moment.

What perhaps gets lost in the academic perspective on type checking at compile time because it's assumed that the audience for such papers takes it for granted is that "compile-time checking for potential errors" and "compile-time type checking" are the same thing, thanks to the Curry-Howard Isomorphism, which, in a nutshell, says that (static) types are propositions, and functions of that type are proofs. You find this implemented quite literally in proof assistants like Coq, but you can take advantage of the insight in programming languages with rich type systems, such as OCaml, Haskell, or Scala. :-)

David Pollak said...

I've been happily coding in Scala for the last 2 years.

Unlike any other language I've used (C, C++, Objective-C, Java, Ruby, etc.), the kind of thinking I have to do as a library consumer and library producer are radically different.

As a library consumer, I rarely concern myself with Scala's type system... or most of the other language complexities. My consumer code looks and feels a lot like my Ruby code did. I've got great DSL support. For the most part, the types that the compiler doesn't infer are the ones I need to document anyway. But, unlike my Ruby code, I only need 50%-60% test coverage (vs. 95% coverage) to have stable, deployable code.

As a library producer (http://liftweb.net), I spend a lot of time reasoning about the types of parameters. This allows the compiler to flag illegal types (e.g., passing an Int into a query against a VARCHAR column). The type system also allows me to reason about my code and how the consumers will use my libraries in a way that I could not do in any other language I've ever used.

Yes, Scala does have some rough edges (the () vs. {} issue bugs me a lot). On the other hand, Scala's cleaner than Ruby or Java.

Dan Nugent said...

Ian: The Monads in Haskell are really more for dealing with the laziness and absence of side-effects than anything regarding static typing.

The types of Monads are to make them all work nicely with a small set of standard operators.

So... perhaps you have not yet truly understood Monads? ;)

jvdneste said...

But why static typing *or* dynamic typing? Why not both? C# 4 looks like it is going to be the first mainstraim language to support both.

But C# and friends still lack python's ever-refreshing pragmatism.

The only new thing that comes close is Clojure, of which I am rapidly becoming very fond.

Matt said...

There are some syntactic oddities in Scala for sure, but the more programming I did in Scala, the more I realized they were conscious engineering trade-offs that make the code more readable 95% of the time.

I actually saw Martin's Scala talk at POPL 2006 (and Lex Spoon was my Ph.D. sibling before he went off to do Scala). I remember being skeptical at the time. But, last year, I finally started using Scala to replace an old Java HTTPD, and I was really impressed with how well it fused the functional with the OO. I really like the trait-based multiple inheritance system, too.

My biggest annoyance with Scala (and other OO languages) is the lack of support for promoting the return types of certain methods during sub-classing. But, this has been fixed with higher-kinded types, and should be in the language fairly soon. So, I'm optimistic about Scala's future.

Tomas said...

It's been a year since I started using Scala, so I'm by no means an expert. While Scala's type system is complicated when described, actually using it isn't that bad, once you get used to it. The type system has certainly been put in for a reason.

The worst thing about the language in my experience is that in order to make the code neater and smaller, a lot of things are optionally implicit (types, function invocation, object construction, object coercion). This can make the code harder to read later.

All in all, I'll take Scala over Java anytime as a language, but there are of course an abundance of situations where I feel I would be better served by some language other than Scala or Java.

Alex Payne said...

I'm a bit biased, as I'm writing a book about Scala for O'Reilly, but type theory in Scala is as complicated as you want it to be. Day-to-day programming involves little to no reasoning about types - you either let the type inferencer do its work or help it out with type annotations when it can't figure out your intent. If you want to get fancy with typing, you can, but it's not mandatory.

Having written in dynamic languages - Python included - for the last several years, working in Scala is a tradeoff. In Scala you spend more time up-front thinking about the types in your program, but less time debugging later. I'll take that tradeoff when writing code for production systems any day.

For smaller applications, I'd say it's a matter of preference; both static and dynamic languages have their place. In Scala's case, I've been able to write small programs - XML parsing, that sort of thing - with the "feel" of code written in a dynamic language but boasting many times better performance.

Yegge's jesting should be taken with a grain of salt - here's a guy who's been re-implementing a JavaScript interpreter in thousands of lines of Emacs Lisp. He's clearly decided that his preferred poison is dynamism. I respect that - he's clearly a virtuoso dynamic programmer. That doesn't mean other people can't grasp type theory, though.

As for Haskell: it and Scala are fundamentally different languages. Scala attempts to bridge OOP and functional programming, whereas Haskell is a pure functional language in the strictest academic tradition. I think the two languages attract a different type of programmer.

In Haskell's 18 years on the programming language scene, it's been in the perpetual role of the underused theoretical ideal alternative. I can't count how many times I've seen "perhaps Haskell?" since researching languages became a hobby of mine. I'm seeing more and more programmers getting real work with Scala, not musing about its theoretical possibilities. I find that pragmatism encouraging.

There's nothing preventing one from writing Monads in Scala. Scala is a perfectly competent functional languages, and all the functional "patterns" apply readily. James Iry and Tony Morris blog frequently about Monads in Scala.

I will concede that ironing out the syntactic edge cases would be a welcome change. That said, I don't find them burdensome in daily work - no more so than remembering Python's conventions, certainly.

At any rate, thanks for exploring our little - but growing - corner of the language landscape.

daryoush said...

The best thing about Scala is that it is the first step to get out of Java and OO. I suspect it would do for others what it did for me. As soon as I started looking at the Scala it was obvious that there is a lot more to functional programming than just function type. I started looking at Haskell and ErLang. The Language is a lot cleaner but more importantly they are both better tools to study functional programming.

Riobard said...

It feels to me that Scala's syntax is a huge compromise: you've got some flavor of Java, some of Python; way better than Java, but much worse than Python. (I like dynamic type)

It even has a half-baked Actor model trying to mimic Erlang's, albeit without Erlang's elegance.

Hate to program in it -- lots of little nasty stuff to worry about. Or maybe I am spoiled too much by Python? :P

Pramod said...

I tried learning Haskell a few months ago, and didn't make very much progress. It seemed to me that Haskell isn't quite a language that one can learning by hacking around - one has to put quite a bit of effort into reading the documentation carefully - almost like reading a mathematical textbook! From a hacker perspective, this was a little off-putting.

I didn't really have much use for Haskell, but I've suspended the learning the project for now. In contrast, my experience with learning Scala has been much more pleasant. I have to concur with the commentors who say that programming most straightforward things in Scala is straightforward. I have run into a few warts in the syntax now and then but usually the problems are manageable.

There can be no question about the fact that a dynamic language is going to be much simpler and cleaner. What remains unclear to me is if dynamic languages will every approach the performance of static typed languages for compute intensive tasks. For now, the answer seems to "no", and so innovations like Scala which hide a lot of complexity to make static typing usable are to be encouraged.

Peaker said...

Guido said:
"""
The cynic in me says that this is at least in part due to a long-standing academic interest in types, which makes it easy to get papers about novel type checking approaches to get accepted than papers about other topics related to compile-time checking.
"""

Guido: Perhaps you should look at "dependent-types". Types don't really mean what a lot of people think they mean, and they can incorporate any and all information about the desired results of a computation. So type-checking can, in fact, encompasses all of these "other topics related to compile-time checking".

Yaron Minsky said...

I'm not sure where the future of compile-time checking lies, but if you're looking for an example of an effective statically typed language that is in a practical form now, ML is worth learning (OCaml is my favorite, but what I'm saying goes for SML and F# as well.) As I've argued elsewhere, ML is in a kind of sweet-spot in programming language design. Its type system is just expressive enough to take on the vast majority of programming tasks in a natural way, without becoming too complex and unwieldy (so long as you ignore the object system.) The fact that side effects are not banned reduces the need for fanciness in the type system. Also, it's very efficient and (importantly) its performance is easy to understand and predict.

It's not all wine and roses, of course. The syntax is a sore spot (it's not complicated, but it has a number of error-prone corners to it) and the standard library is thin.

In any case, if you want to give static typing a fair shake, I do think ML is a better candidate to look at as opposed to some of the more ambitious projects like Haskell or Scala. To be clear, Haskell is a great language (I know little about Scala), but if you're looking for a language that is pragmatic right now, I think ML is the best candidate.

James Iry said...

It's interesting that you mention both for comprehensions and monads - the for/yield construct in Scala is a loop-looking take on an OOish form of monads. Think of it as Haskell's "do" in a different form.

There's a reason for Python 3 nee 3000 - Python 2 had grown some strange warts. There were experiments that didn't pan out, new features that pretty much subsumed old features, curious differences in apparently similar constructs, and a general feeling that some parts of it didn't quite fit with the Pythonic philosophy.

Yet, upon seeing a few of those warts in Python 2.x, should somebody have thrown up his hands and say "this language is hopeless!"? I'm sure you would say, on the contrary, for all the flaws you felt were in Python 2 the vast majority of the language was still pretty nice and in keeping with the design philosophy.

Scala's not where Python 2 was, but one can definitely foresee a need for a "Scala 3000" effort.

That said, I'm opposed to dumbing down the type system. There are plenty of languages out there with more limited type systems and it's good to have that spectrum of choice. Scalars pay a price in the limited type inference, but full type inference is only one possible design goal in the infinite dimensional landscape of language design.

Doug Holton said...

It only takes about 15 minutes to get the gist of Scala:
http://www.artima.com/scalazine/articles/steps.html

Then grab the Netbeans 6.5 scala plugin: http://www.scala-lang.org/node/353

Here's an example using scala and the Pulpcore applet/game engine (an alternative to flash/javafx):
http://pulpcore.googlecode.com/svn/trunk/templates/scala/src/

Howard said...

I have to agree with the comments on Clojure; this feels like the step forward (into the past, via the Lisp heritage).

JodaStephen said...

The language I'm keeping an eye on is Fan .This is because it is a clear evolutionary language from Java/C# and doesn't try to over-complicate with excessive FP or syntax noise. Fan is static typed but has a nice dynamic element, allowing you to invoke a method dynamically with a different operator.

Scala scares me, in that some of its proponents are pushing it as the mainstream replacement for Java. I just think its too complex to fill that role.

pk11 said...

i think many ways the scala complexity claim is similar to the so-called whitespace 'issue' in python.

in that sense that the whitespace issue is usually brought up by people who usually just glanced through the language. (not to say first impressions are not important! in fact the scala community needs to address this claim the same way the python community addressed and defended both the explicit self and the whitespace issues over time.)

programming in scala 'the java way' using only a few functional features of scala feels actually simpler compared to java, not more complex (so while the language grammar might be more complex the client code is definitely simpler).

ps1: i like both scala and python

ps2: i see clojure and fan already mentioned in this thread, can not wait for a groovy or jruby plug:D

Grom said...

What do you think of Evolutionary Programming (ala what was in ECMAScript 4 with optional types, like and wrap operators; see http://lambda-the-ultimate.org/node/2550)

Jim White said...

As OCaml was mentioned, I'll point out that there is (not very well known) good implementation for the JVM called OCaml-Java by Xavier Clerc.

http://ocamljava.x9c.fr/

You can try out all the languages discussed in this thread and create "live" tutorials with IFCX Wings.

http://www.ifcx.org/

Flying Frog Consultancy Ltd. said...

In other words, you smelled a guava and decided you don't like fruit.

Scala is one of many languages pushing the boundaries of type checking. They all have significantly different characteristics and trade-offs so you cannot draw any conclusions about the whole family without trying each and every one of them. You should at least have a look at SML, Haskell, OCaml and F#.

Indeed, if you were going to try only one I'd have expected it to be F# because it has at least left academia.

bbarber said...

Kudos to the thoughtful comments.

I expected to be reading responses from Python fanboys saying "Yeah! I looked at Scala for 10 minutes and realized that it sucked too!"

Thanks for the constructive comments about additional languages to consider and for the nuaunced defences of Scala's approach to typing and language features.

rogerdpack said...

@someone up there: python's psyco basically works using types [dynamically discovered at run-time] then optimizes using them.

So..what's the difference type and "pleasure" wise between scala and clojure?
-=r

Ricky Clarkson said...

The difference is that Scala is typed, whereas Clojure is untyped, in the sense of the "untyped lambda calculus". Though Clojure is a lisp, and programming in lisp is a pleasure just because the syntax is so regular.

Puzzler said...

Python has been my preferred programming language for several years, but I've often wished I could write some parts of my program in some kind of "typed Python" in order to get better support for programming in the large, easier and less error-prone refactoring, and better performance.

On top of that, I've always been a fan of functional programming, and I wish Python had a richer set of immutable data structures.

So I've had my eye on the various up-and-coming functional languages. I vowed earlier this year to give a serious try to the first functional language to come out with a decent IDE. F# now has its own flavor of Visual Studio as an IDE, so that's the one I ended up spending some time with. It was very frustrating and disappointing, much of which was due to the type system. Even though, in principle, I'm not opposed to static typing, I keep finding that it's just more hassle than it's worth.

In 2007, I spent some quality time with Scala. David Pollak's comment is very insightful. As a "library consumer" you don't have to know too much about the type system, and working at that level, Scala actually feels pretty nice. As a "library producer" it's much more involved. DP says he likes the power it gives him to specify and reason about the way his library code will be used, but I found the complexity of the type system to be somewhat overwhelming.

But I still think that Scala has a shot at being a viable replacement for Java, because it is possible for many programmers to work at a level where that type system complexity can be ignored.

In the past few months, I've been exploring Clojure, and it's fun and satisfying in a way that I haven't felt since I first discovered Python.

So I'll come out and say it: Clojure is Python for functional programmers. I believe that much of the pleasure of coding in Python comes from the rich set of built-in data structures, namely, tuples, lists, dicts, and sets, and a lot of handy syntax (e.g. slices), and functions that work across these types in a fairly consistent way. These features combine to make programming many things a snap, with code that is concise and readable.

Clojure similarly comes with a rich set of built-in, easy-to-use data structures (including vectors, maps, sets, and lazy sequences which roughly correspond to Python's lists, dicts, sets, and generators), handy syntax for using those data structures, and functions that work across these structures in a consistent, pleasing way. The main difference is that in Clojure, all the built-in data structures are immutable. So, for example, when you update an entry in a dict, you are actually creating a new dict (which shares data with the original so these operations are efficient). I find that programs written with immutable data structures are often easier to reason about.

Aside from Clojure's choice that all the built-in data structures are immutable, I would say that the spirit of the two languages is extremely similar.

Of course, Clojure uses a Lisp-style syntax which has its advantages and disadvantages. I find Lisp-style syntax to be less readable than Python, but it allows for macros, which can be a very powerful tool.

So although 2008 was the year I hoped to find a statically-typed language that I liked using, I've given up for now, and I'm back to dynamic languages. Python's still my go-to language, but Clojure is my language-to-watch.

Raoul Duke said...

@interfacing with jvm + java libraries, i hope that GScript comes out some day.

http://guidewiredevelopment.wordpress.com/2008/07/15/the-necessity-of-type-inference/

(i have no affiliation.)

Rob said...

Guido. Frankly I am disappointed in you. Since you have a lot of pull in the python world, you are trying to use it to downplay scala. You should be more sensible in your comments considering the responsible position you are in. It seems your comments are more due to fear that Scala is someday going to overtake python. Python fanboys will of course blindly believe what you say. Scala is so much more advanced than what Python can hope to be. I have been happily using it for 2 years now and it has only improved.

Your review is very blind-sighted and I won't be taking your posts seriously from now on.

Smee said...

"Guido. Frankly I am disappointed in you. Since you have a lot of pull in the python world, you are trying to use it to downplay scala. You should be more sensible in your comments considering the responsible position you are in. It seems your comments are more due to fear that Scala is someday going to overtake python. Python fanboys will of course blindly believe what you say. Scala is so much more advanced than what Python can hope to be. I have been happily using it for 2 years now and it has only improved.

Your review is very blind-sighted and I won't be taking your posts seriously from now on."

This post is obviously biased and I would take Python over Scala any day.