A Quick Look at Scala

Here are a few fairly simple steps in Scala that show a little of its flavor and power, followed by a bit of comparative Java code.

      • Let’s start by creating a map from integers to their English names. We’ll populate the map for integers 1 and 2 as examples, and make the name of any integer not in the map “UNKNOWN”.
        val map = Map( 1->"one", 2->"two" ) withDefaultValue "UNKNOWN"
      • Now let’s produce a list of the values from that map that have even keys. That is, for each key-value pair in the map, if the key is even, we want the value.
        for ( (k,v) <- map if k%2 == 0 ) yield v
      • OK, now generalize that by writing a method which, given such a map from Int to String and any test function for the keys, returns a list of those values whose keys pass the test (i.e. the test function returns true).
        def pickValues( map: Map[Int,String], keyTest: Int => Boolean ) =
          for ( (k,v) <- map if keyTest(k) ) yield v
      • Next let’s generalize the method to work with any type of key and any type of value. That is, we’ll write a method which, given any map and a test function appropriate for the map’s keys, will return a list of those values whose keys pass the test.
        def pickValues[K,V]( map: Map[K,V], keyTest: K => Boolean ) =
          for ( (k,v) <- map if keyTest(k) ) yield v
      • Now let’s invoke that last method to get the names of even numbers from the map we created earlier.
        pickValues( map, (x:Int) => x%2 == 0 )
      • That’s already pretty nice.  With some more advanced tricks (which I won’t go into here) we could make that
        map pickValues ( _%2 == 0 )
      • But in reality you probably wouldn’t write this at all because Map has a method that produces the subset Map whose keys satisfy some predicate.  You could just ask for the values of that subset.
        ( map filterKeys ( _%2 == 0 ) ).values

Did you follow that? My guess is that even if you aren’t a Scala developer, you can more or less understand what’s going on without someone having to explain the details. And we very quickly arrived at a fairly general-purpose bit of code that is straightforward to use.

Now for some Java.

        • First let’s create that map.
          Map<Integer,String> map = new HashMap<Integer,String>();
          map.put(1,"one");
          map.put(2,"two");
In addition to being more verbose and less readable, that falls a bit short in that it doesn’t specify a default value.  You could use some other collections library if you wanted that, but the JRE Map interface and its implementation classes just don’t have that feature, so you would either have to handle defaulting each place you used the map or write a method to take care of that once and for all.
        • Now produce a list of the values from that map with even keys.
          List<String> list = new LinkedList<String>();
          for ( Integer i : map.keySet() ) {
              if ( i%2 == 0 ) list.add( map.get(i) );
          }

The next step would be to generalize this to a method which takes a test function on Integers. We could do it, of course, but we’re already at the limit of what most people would be willing to do in order to avoid repeating themselves. Since there are no functions in Java, what we wrote in Scala as

(x:Int) => x%2 == 0

would become an unwieldy anonymous inner class. Most people probably wouldn’t bother. If you are serious about wanting to do such things, then at the very least you should look at Google’s collection library for Java. But even that is going to be much less friendly than Scala.

Perhaps more importantly, the Java collections are not immutable. This may not seem like a big deal when you are first starting out in Scala, but it really has far-reaching implications in a concurrent environment.

Part of the reason I wanted to blog about this is that in the now-infamous Yammer letter in which an engineer who likes the Fantom programming language tries to make Scala sound like a horrible programming language with a horrible community, he enumerates the things he had to explain to new members of his team for even the simplest usage of a collection:

        • implicit parameters
        • builder typeclasses
        • “operator overloading”
        • return type inference
        • Traversable
        • TraversableOnce
        • GenTraversable
        • Iterable
        • IterableLike
        • Should they be choosing the most general type for parameters, and if so what was that?
        • What was a =:= and where could they get one from?

Really? All of that was necessary in order to understand even the simplest use of a collection? As you can probably tell, I am not a fan of his teaching style.

Rather than burying the magic necessary to create a really good collections library in the compiler, where it would be unavailable to the rest of us, the Scala designers made the type system powerful enough to allow a high-quality collections library to be written as ordinary Scala code. The good news is that that means more power for us to use in our own code. Unfortunately this also means that when you look at detailed type signatures in the collections library you see the many traits and classes needed to create it. This is called the “visible plumbing problem.”

Recently the API documentation has been changed to make the less interesting parts of the plumbing less visible. And even so, the type signatures can be a little daunting for newcomers. But nobody should be deceived into thinking that they’ll have to understand GenTraversable, IterableLike, etc. in order to use Scala collections — that’s just FUD. The only reason I can think of for deliberately dragging someone new to Scala through all of that plumbing is to try to convince them that Scala is hard. When teaching someone to drive, do you start by popping the hood and explaining how the drive train works?

Fortunately I didn’t have that guy’s help getting started.

[other Scala posts]

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: