An Impromptu Scala/Groovy Competition

I got a kick out of this post. The author, who was learning Scala, came up with a solution to this problem. Don’t bother to analyze it, but here is his solution (digits — what that post calls bigNum — is a String of 1000 digits):

def product( digits:String ) = { digits.map( java.lang.String.valueOf(_).toInt ).reduceLeft( (prod,c) => prod*c ) }
digits.sliding(5).toSeq.map( s => product(s) ).max

He was really happy with it and, understandably, wanted to share it and explain how it works.

Well, the very first comment was a somewhat tacky “mine is better because it’s shorter” Groovy solution (don’t bother with it either), albeit shorter mostly by not breaking out some of the work into a function as the post’s author had chosen to do for clarity (I’ve changed variable names to match the Scala version):

( 0 .. digits.size()-5 ).collect { digits.substring( it, it+5 ).toList().inject(1) { prod,c -> prod * c.toInteger() } }.max {it}

But then a more seasoned Scala developer absolutely blew the Groovy solution’s doors off with this:

digits.map{_.asDigit}.sliding(5).map{_.product}.max

That is, convert the digit characters to their numeric values, map every sliding window of five numbers to its product, and find the maximum of those. Assuming you know what a “sliding window” is and what map does, it’s hard to imagine a much more readable solution.

Now the truth of the matter is that having the shortest solution is usually not nearly as important as having a maintainable (understandable and non-fragile) solution, but in this case the Scala solution is far better on all of those counts. Also, Scala code will often be longer than the equivalent Groovy code, because Scala is statically typed. Whether or not performance, and catching type errors before you ship, are worth having to specify some type information is up to you. But in this case those who bragged about Groovy have good reason to be embarrassed.

But there was more. The ill-fated Groovy challenge was followed by another comment saying, effectively, that the Scala code was unreadable and that clever coders should be fired and replaced with average coders who write three times as much code in Java to do the same thing, because then everyone will understand it later.

Really?

If a company I owned stock in expressed that attitude, I would start thinking about putting in a sell order. There are very good business reasons to use modern programming languages, and there are very good business reasons to hire smart software developers. I am bewildered by people who think it is better to stick with older, less capable languages so that they only need mediocre staff. Good luck!

There’s a big difference between hard-because-unfamiliar and obtuse. The seasoned Scala coder’s solution is way more understandable, to anyone who knows Scala, than an equivalent Java solution would be to another Java developer.

But even if it weren’t understandable, to you — even if you didn’t have any idea what those methods do, or couldn’t synthesize their collective effect in your mind — it is really easy to figure such things out in the REPL. Just start by evaluating some subexpression and iterate toward the whole thing, recalling the previous line with an up-arrow and adding to it:

scala> val digits = "9873459873"
digits: String = 9873459873
scala> digits.map{_.asDigit}
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(9, 8, 7, 3, 4, 5, 9, 8, 7, 3)
scala> digits.map{_.asDigit}.sliding(5)
res1: Iterator[scala.collection.immutable.IndexedSeq[Int]] = non-empty iterator
scala> digits.map{_.asDigit}.sliding(5) foreach println
Vector(9, 8, 7, 3, 4)
Vector(8, 7, 3, 4, 5)
Vector(7, 3, 4, 5, 9)
Vector(3, 4, 5, 9, 8)
Vector(4, 5, 9, 8, 7)
Vector(5, 9, 8, 7, 3)
scala> digits.map{_.asDigit}.sliding(5).map{_.product} foreach println
6048
3360
3780
4320
10080
7560
scala> digits.map{_.asDigit}.sliding(5).map{_.product}.max
res4: Int = 10080

For very little effort we have walked through the code step by step as it transforms the data into the solution. Given a working knowledge of Scala, the most junior developer on your staff could do this.

The REPL is a fantastic tool in the developer’s toolbox. Back when IDE support for Scala was young and unstable, you’d see comments about how tool support for Scala was not as good as Java’s. It was a legitimate concern, but even then Scala had a nice REPL and Java did not.

And now there is a “Scala worksheet” in Eclipse and IntelliJ that allows you to do such explorations in a way which is often more convenient, and these explorations can be stored alongside your code as documentation. And because Scala is a statically typed language, these tools can look up and complete method names for you, a big time-saver. So the guy who comes along in six months and has to figure out what some functional Scala code does is going to find that much easier than reverse-engineering the equivalent imperative Java code.

But please, go right ahead and fire those smart software developers who insist on programming in modern languages. We want to hire some!

[other Scala posts]

About these ads

One Comment

  1. Posted March 18, 2014 at 10:54 pm | Permalink | Reply

    I’ll admit, by the way, that IDE support for Scala still needs work. It’s certainly usable today, but IntelliJ uses their own incremental compiler and it sometimes complains about perfectly good Scala. Eclipse uses the official Scala presentation compiler, so it is much better about false warnings, but it has plenty of warts of its own. Looking forward to better!

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

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: