Sunday, December 4, 2011

Scala vs Groovy

I've been working recently on a project based in Scala and just started to use SBT for the build tool. A significant project I have, my accounting system (G'Kané), is written in Grails.

As I'm flipping back and forth right now, a few things are sticking out.  I'll probably update this as I go along, but so far:

I really like the ? operator in Groovy, getThing()?.doSomething(), only runs doSomething() if getThing() returns a non-null value.  The only way I know how to do this right now in Scala is via a match statement, possibly using the Option[] construct, which is really clunky in comparison:

getThing() match {
  case Some(p) => p.doSomething()
  case _ => null
}

On the plus side for Scala is case classes.  The same thing that causes the above travesty is also something to be rejoiced in.  I know I can pass a map to a Groovy constructor:

new Thing([name : "myThing", value: 4])

but it's completely type unsafe.  In comparison, a Scala case class has a default constructor with the properties:

new Thing("myThing", 4)

Granted, it does mean the order has to be correct, which is a bit of a pain, but you do get type sanity.

In the black-eye department for Groovy is the bewildering mix of Groovy method declarations and Java style one, and in-between.

def thing = { "something here" }

but if I want it typed, suddenly it's back to almost Java:

def String thing() { "something here" }

Having untyped methods in Scala seems pretty near impossible though, so I suppose it's not quite fair, but:

def thing : String = { "something here" }

in and of itself seems closer to the syntax that would seem like it should be idiomatic for Groovy, though it's actually Scala. This debacle leaves us wondering if we should be calling Bar.thing, or Bar.thing() in Groovy, and it might change, even though the function of the method didn't.

The Grails compilation on the fly feature, whilst nice, at least in theory, is a source of major pain for an old hacker like me who has the Save key-press burned into the brain as a function to be performed after every single change made in a file.  The poor on-the-fly compilation just gets really angry because I frequently save a file multiple times per minute, and also when it's far from working.  SBT has a similar feature, but it's not coupled to my app in progress (at least not yet).

On traits and interfaces: I'm really loving traits in Scala.  They are fun and a neat way to implement cross-cutting concerns in a way that's not quite as all-powerful as Aspects, but yet still code-visible to a mere mortal.  Interfaces in Groovy, I honestly still don't understand how to work that.  I've looked it up a few times, but it either won't stick, or just hasn't made sense to me yet.  For instance, I have a set of services which all do similar things that I would normally group in an Interface in Java.  They are responsible for creating a Mapping description object.  They have a single method columnMap() which returns a ColumnMap object.  I'd create an interface called ColumnMapper or something in Java to describe this contract.  In Groovy, I can create an abstract class, but where does it live?  In my Grails view in IntelliJ, it seems a bit unclear.  Do I make it a service that's just declared abstract?  What happens if I try to bind that abstract class?  If it were Java I'd get a compiler error, I'm guessing I'd get a runtime error in Groovy, and I'm not sure if my IDE is smart enough to figure it out and show it as an error.

Speaking of IDEs, the Scala plugin for IntelliJ 11 is improved, but still has a ways to go.  It gets confused sometimes about a project, and will only let me create scripts, which then turn into the appropriate icon once I create the code.  Bit weird.  Still, given the very weak type binding in Groovy, which leaves the poor IDE guessing more often than not, I'm currently leaning to Scala on the matter of code inspection, at least in IntelliJ.

1 comment: