Archive

Posts Tagged ‘learning’

Getting to know Scala

January 10th, 2009 3 comments

It’s conventional wisdom that a programmer should probably learn one new language every year. By my count, in my 10 years as a “professional” programmer I’ve done non-trivial projects in eight languages (chronologically: Matlab, C, C++, Visual Basic, Lisp, Tcl, Python, Java). So, I’ve got a pretty good average, but a lot of that was concentrated in the first several years. For that last few years, I’ve been in a mostly Java rut for better or worse.  In an attempt to break the monotony, I started learning Scala shortly before the New Year. From the web site:

Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages. It is also fully interoperable with Java.

Scala appeals to me on a few fronts. First, it’s functional aspects are an area I really haven’t had much experience with other than a brief stint in Lisp many years ago and an occasional lambda in Python. Second, because it runs on the JVM, there’s a somewhat compelling case that I could actually use it on a project someday without throwing out all of my Java work from the past few years.

Getting Started

I started out by reading Ted Neward’s excellent series of articles on Scala. I read them just to get a feel for the language, but never actually tried running any code. After reading that series, I decided to take the plunge and bought the brand new Programming in Scala book in both digital and analog forms.  It’s really a pretty good book. It’s well written and doesn’t gloss over technical details. The book is technically a tutorial which means it introduces the language in stages. Overall, this is a good approach, but there were a few points that were teasers for later chapters that I wish they would have covered immediately. Two examples:

  • The idea of companion objects for “new-free” constructors like List() and Map() is mentioned early on, but they don’t say how to actually do it until much later. I wanted to know right then!
  • They briefly discuss val vs. var. vs. def and the UniformAccess Principle, without giving an example. I had to hunt through the rest of the book to find out how to implement it.

So now I had the book, time to write some code…

The Project

Oh, first I guess I should say what my “learning Scala” project is. I’m building a very simple, very naive rules engine, rooscaloo, in the spirit of Drools or Ruleby. In a nutshell, users write rules that match patterns in memory and do something interesting when a match occurs.  Memory is populated by facts, which in my case are just plain old Scala objects. The matcher is a simple implementation of a rete network which has a lot of list manipulation and traversal which I hoped would map nicely onto Scala’s functional capabilities.

Choosing an IDE

First I had to decide on an IDE. The Scala compiler, scalac, is a command-line tool, so of course, vim + ant or something was always an option. But, I’m old and lazy now, so if I can transfer my [ctrl + space] programming habits from Java to Scala, you better believe I will.

Since I’m generally partial to Eclipse, I first tried out the Scala Eclipse plugin. A somewhat sad trend I’ve noticed in the Eclipse universe is that the core Java tools, the JDT, are generally rock solid and everything else (including the several Eclipse plugins I’ve built myself) just doesn’t work that well.  The complexity of the Eclipse API, especially the threading model, can’t help much.

Anyway, I installed the plugin, created a test project and things seemed to work pretty well.  I started coding and went to add my first unit test. Since I know JUnit, and like Eclipse’s green bar, I went with that. I added the JUnit library to the project in the usual way and … my unit test code wouldn’t compile, couldn’t find JUnit. I fiddled around with manually adding the JUnit jar, restarting Eclipse and some other stuff and eventually got it to work, but wasn’t that confident. As a test, I tried creating a fresh Scala project and immediately adding JUnit support and that worked flawlessly.  These are the little details of Eclipse plugin development that really kill you.

Finally, I continued coding, and at some point decided to rename a file. This was a mistake. It basically killed Eclipse, flooding it with errors and leaving the project in a really weird state when I restarted. That ended it for me. I really need to be able to rename files.

My next stop was the NetBeans Scala plugin. For most Java development, I’ve generally found NetBeans pretty inferior to Eclipse. The editor is more clunky, and having to manually build my code just seems prehistoric.  Anyway, I gave the Scala plugin a try and so far, I’ve been pretty happy with it. JUnit support “just worked”. Code completion works about as much as I’d expect it to (maybe 50%, so worse than Java, but better than a lot of dynamic languages), the editor is bearable, and the debugger seems to work fine.

The only issue I’ve had is that one of my source files seems to give the editor (or compiler, or whatever is behind the editor) fits. I’ll type a character (any character) and the whole UI will freeze for a few seconds.  I’ve seen similar issues reported on the scala-tools mailing list, so maybe it’s a more general problem.

I’ll stick with NetBeans I guess until something better comes along.

Language Highlights

I’ve only scratched the surface of Scala (and actually only gotten through the first 16 chapters of the Scala book), so here I’ll just present my favorite parts of the language that I’ve actually used.

Now that I’ve written it, this is a pretty haphazard list. I’m going to leave it though mostly because I’m too tired to rethink what I want to say…

Option[T]

Option[T] is a Scala datatype that encapsulates the sentinel value role usually filled by null in Java. For example, in Java, Map.get() returns null if the value isn’t present. This is an incredibly common pattern.  Because of it, I spend my programming time trying to decide whether a method can return null or whether it is safe to pass null as an argument to a method, etc. Sometimes it’s documented, others I have to guess or just test and see what happens. Option[T] has two possible values: Some and None. Some holds a non-null instance of a type T. By consistently using Option[T] in APIs, client code is forced to check for null return values and knows when a parameter accepts a null value. Testing for null (None, actually) is done with Scala’s really cool pattern matching construct:

    val name = getUserName()
    name match {
        case Some(n) => println("User name is " + n)
        case None =>    // Do nothing
    }

This can get a little tedious, but Scala has a nice solution. First, I’ve found it useful to think of a Option[T] as a collection of T that can hold exactly 0 or 1 values. Each collection in Scala has a foreach that takes a function to execute on the members of the collection. So, Option[T] has a foreach method as well. The pattern match above translates to the following foreach call:

    getUserName().foreach(println("User name is " + _))

foreach, map, and friends

Scala collections support functional iteration, that is you pass a function to the collection and it is called for each member in the collection. This is such an improvement over Java, even Java’s kinda new for-each construct. Here’s an example of rete left activation from my project:

    val nt = newToken(Some(token), item)
    children.foreach(_.leftActivate(nt))

In Java this would look something like:

    final Token nt = newToken(token, item);
    for(BetaMemoryChild child : children)
    {
        child.leftActivate(nt);
    }

which isn’t that bad, but it really adds up, especially when the body of the loop is more complicated, or if the member type is something like Map.Entry<String, Person>.

Type Inferencing

As indicated in the examples above, Scala uses type inferencing which means it figures out the types of variables based on what’s assigned to them.  This really cuts down on all the Java boilerplate while maintaining static typing. There’s a pretty good explanation here.

mkString()

This is a really stupid little thing, but every Scala collection has a mkString() method that takes a string delimiter and joins the values in the collection:

  scala> val r = List(1, 2, 3, 4, 5)
  r: List[Int] = List(1, 2, 3, 4, 5)

  scala> r.mkString(", ")
  res0: String = 1, 2, 3, 4, 5

If I had a nickel for every time I’ve written StringUtils.join() in a Java project …

Conclusion

Overall, after 10 days of use, I’m loving Scala. I think I’ve barely scratched the surface of what it can do. My little rules engine, rooscaloo, has been a pretty good driver for learning the language so far. It has enough algorithmic and data structure variety that I’ve been able to find ways to apply Scala constructs in many areas. It’s probably not going to be very efficient or powerful, but it will have served its purpose.

I’m looking forward to trying out parser combinators to define the rule language. Right now, I’m just building rules programmatically, which is still far easier and more readable than the equivalent Java code.  I initially thought I might be able to encode the rules as an embedded DSL in Scala with it’s incredibly flexible syntax, but I’m not sure I’ll be able to get the affect I want and I need an excuse to try out the parser stuff :)

Links

Below are some links to information on Scala that I’ve found particularly helpful:

I’ve also spent a little time on the Scala mailing lists and have found the community responsive and friendly.

Categories: scala Tags: , , ,