
Scala offers many ways to abstract and reuse code, but one area where this is not entirely obvious is exception handling. Sure, when it comes to error handling, there are good ways to write elegant code: use Option or Either and soon Try. But when it comes to exceptions, for instance when interfacing with Java code, one has to write tedious try-catch blocks. In this post I will briefly describe a few utility methods in the standard library that are undeservedly obscure. I got the idea of this blog post when answering this stack overflow question (though my answer is not the most voted, I still think it's the better solution
).
This little utility class and allows the programmer to abstract over common patterns of handling exceptions. Let's start with some code that catches an exception and converts it to Option.
import scala.util.control._
object exceptions {
import Exception._
catching(classOf[NoSuchElementException]).opt {
List().head
} //> res1: Option[Nothing] = None
}
catching loosely follows the builder pattern and constructs a Catcher object, with user-configurable logic for what to catch and how to handle the exceptions. In our example, we pass an exception type and configure the catcher to convert the result to an option. Obviously, if an exception is thrown the result is None
In exactly the same way we could convert it to Either:
import scala.util.control.Exception._
object exceptions {
val xs = List(1)
catching(classOf[NoSuchElementException]).opt {
xs.head
} //> res0: Option[Int] = Some(1)
catching(classOf[NoSuchElementException]).either {
xs.head
} //> res1: scala.util.Either[Throwable,Int] = Right(1)
}
catching takes any number of exceptions and it is the most flexible way to use this library, but a few patterns come up often enough to warrant their addition to the standard library:
nonFatalCatch is, unsurprisingly, a catcher that re-throws fatal errors. Given that the Scala compiler sometimes relies on exceptions for control flow (like non-local returns), it's a very bad idea to catch any of thoseignoring(e1, e2, ..) evaluates a block and catches given exceptions (it returns Unit, so this can be used only for side-effecting codefailing(e1, e2, ..) evaluates a block and catches given exceptions, returning None if the block throws an exception, wrapping the resulting value in an OptionfailAsValue(e1, e2, ..)(default) catches any of the given exceptions and returns a given default value if the block throws. For instance,
failAsValue(classOf[Exception])(-1) {
xs(2)
} //> res3: Int = -1
Catchers can be customised even more, and that's what I used in the SO answer. withApply can be used to pass a function that handles the exceptional case. For instance:
def logError(t: Throwable): Int = {
println("Error: " + t)
-1
}
catching(classOf[Exception]).withApply(logError _) {
xs(2)
} //> Error: java.lang.IndexOutOfBoundsException: 2
//| res3: Int = -1
This example shows how the exception handling logic can be abstracted in a function. We can take this one step further and reuse entire catchers (since they are plain Scala values, there's not much to be done):
val loggingExceptions = catching(classOf[Exception]).withApply(logError _)
loggingExceptions {
xs(2)
} //> Error: java.lang.IndexOutOfBoundsException: 2
//| res3: Int = -1
I've found this utility class very useful when integrating Scala code with an existing Java codebase, and a good example of DSL design.
It took me a while to figure this one out, so I'll write it down for future reference.
We're using maven and tycho to manage builds for the Scala IDE. Our dependencies come both from maven and Eclipse P2 repositories, and http://download.eclipse.org is slow as molasses. Every build loses 4-5 seconds connecting to that repository (even when there's nothing to download). I finally made a local mirror (wget didn't work, so I had to use the official way).
The next step was to make this mirror available to my builds, without modifying the existing poms (it's an open source project, with contributors in several locations). Maven conveniently provides mirrors in a per-user settings.xml file, but for some reason P2 repositories didn't pick it up. It turns out you need to explicitly say it's a P2 repository (thanks to good people on this mail thread):
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
| -->
<mirror>
<id>local-helios</id>
<mirrorOf>Helios</mirrorOf>
<name>Local Mirror of Eclipse Helips p2 repository.</name>
<url>http://iulians-imac.local/~dragos/mirrors/helios/</url>
<layout>p2</layout>
<mirrorOfLayouts>p2</mirrorOfLayouts>
</mirror>
</mirrors>
I just spent a wonderful week in California, and attended ScalaDays 2011. One thing that popped up during one of the talks was that 'Java inner classes in Scala are a challenge'. I was pretty surprised since this came from one of the speakers, and someone I'm sure is a very knowledgeable person otherwise. Of course, you can use Java inner classes in Scala. But first..
Let's call nested a class defined inside another class that is static, and let's call inner class a non-static class defined inside another class. Java uses the same syntax to refer to both nested and inner classes: import Outer.Inner. We'll consider the following example throughout this post:
package test;
public class Outer {
public int base = 10;
public class Inner {
public int x = 10 + base;
}
}
You can use the Inner class either by subclassing Outer, or (less common), by importing and instantiating through an outer instance:
import test.Outer.Inner; import test.Outer; ... Outer o = new Outer(); Inner i = o.new Inner(); i.x;
Java does not distinguish between instance and static members, so the import line looks unsurprising. However, the instantiation syntax is rather weird, making the keyword new look like a member of o, instead of making Inner look like a member of o.
An inner class has access to all members of the enclosing class, final and non-final alike. Therefore, whenever an inner class is instantiated it needs to be passed (implicitly) a reference to the outer instance.
Scala treats inner classes like any class members. Therefore, selection (both for importing and instantiation) proceeds with an outer value and goes on to select the inner type.
val outer = new Outer val inner = new outer.Inner
Note that due to type inference, there was no need to specify the type of inner. What is the type of inner?
val outer = new Outer val inner: outer.Inner = new outer.Inner
We can use the same syntax to import the Inner type in scope:
import outer.Inner.
In Scala, types that depend on a value (the object outer in this example) are called path-dependent types. If we had a second instance of Outer, say outer2, the two types would be incompatible:
val outer2 = new Outer val inner2: outer.Inner = new outer2.Inner
We'd get the following error:
outer.scala:7: error: type mismatch; found : Test.outer2.Inner required: Test.outer.Inner
This is different behavior from Java, where type Outer.Inner matches any instance of Inner, regardless of the outer object instance. It turns out that Scala does have an equivalent type: Outer#Inner. The hash operator performs a type selection. Unlike Java, Scala reserves the dot exclusively for selection on terms.
var inner: outer.Inner = new outer.Inner var inner2: Outer#Inner = new outer2.Inner inner2 = inner // works inner = inner2 // fails
There is still one important difference between the way Scala and Java treat inner classes: mutability. Scala requires paths to be immutable, therefore both instantiation and imports have to mention only vals. The following code doesn't work:
var outer = new Outer val inner = new outer.Inner
outer.scala:9: error: stable identifier required, but outer found.
var inner = new outer.Inner
You may ask yourself why this restriction? It has to do with type members (remember, Scala classes may have abstract type members). If the path to the inner class contains mutable variables, the type of
Innermembers may change during execution. For example, a field may change fromInttoString. In short, it's unsound.
I believe it's this restriction that confuses most people. So what do you do if you need to have mutable outer instances? First of all, you need to use type selection (Outer#Inner) to refer to such types. Second, you need to instantiate them through an immutable alias, for instance by defining a helper method:
var outer1 = new Outer // outer1 is mutable, we need a factory method val inner1 = mkInner(outer1) def mkInner(o: Outer): Outer#Inner = new o.Inner // o is immutable
The
Outer#Innersyntax is not allowed in imports (it's not a path).
With this observations, it should be always possible to use Java inner classes from Scala. I hope this post clarifies a (sometimes shady) part of the Java and Scala interoperability.
Yesterday I finally received my new Apple MacBook Pro, with the new SandyBridge core i7 processor. I was very eager to see how fast it is compared to my work computer (2010 iMac 27''), and what better benchmark than a full build of the Scala compiler?
Here's the result (lower is better)
The first benchmark is the total time for a full build, the following are the bootstrapping steps of the Scala compiler and standard library. For the total time, the laptop is almost 1:30 minutes faster than the desktop!
Here are the two configurations (I ran both builds with a 2.5 GB heap, using Java 1.6/64 bits)
For sure the SSD on my MBP helps a lot, but the processor can't be bad either. I repeated the benchmark by having both computers write to a RAM-disk, and the results were very similar. Of course, the JDK, bootstrap compiler and sources were still on disk (HDD on the iMac, SSD on the laptop), so the laptop still has a signifficant advantage.
While this is certainly a flawed benchmark, and no general conclusions can be drawn, it is nevertheless something I do very often. It's great to see that my new laptop can deliver so well!
It' been over 3 years since I finished my internship at Google, and lots of things happened in Scala-land since. A couple of days ago I went back to my code I wrote back then, and ported it to Scala 2.9.0.RC1. The project is a Scala client library for Google Data APIs.
Google Data (or GData) is an Atom-based publishing protocol that allows CRUD operations over Google services, such as Calendar, YouTube, GMail, etc. It is a very powerful mechanism that allows programatic access to all your Google-based thingies, but being XML-based it is very cumbersome to use directly. Google maintains a bunch of client libraries in different languages that hide all the ugly XML from programmers' eyes.
While at Google, I wrote a Scala client library, and I am still very pleased with the result. I strayed away from their Java client architecture, and for XML handling I wrote a pickler library. However, unlike the original paper that deals with sequential data, I had to make it work with XML trees, which proved a lot more interesting. Briefly, the library allows one to define bi-directional mapping between user types and XML using syntax that's reminiscent of Relax-NG schemas:
def pickler: Pickler[Rating] =
elem("rating",
opt(attr("average", doubleVal))
~ attr("min", intVal)
~ attr("max", intVal)
~ opt(attr("numRaters", intVal))
~ default(attr("rel", text), "overall")
~ opt(attr("value", intVal)))(gdNs)
This code defines an element called 'rating' with an optional attribute average, of type Double, two required attributes of type int (min and max), an attribute with a default string value, and so on. This pickler defines two methods, one from XML to instances of Reminder, and another from Reminder to XML. The library provides type-safe, user-extensible picklers, meaning that the result of unpickling an XML element like
<rating average="2.5" min="1" max="5"/>
will be an instance of the Rating class, and serializing an instance of Rating would generate conforming XML. One of the difficulties I faced was to allow permutation of child elements when parsing (the Atom protocol is very liberal in this regard, and Google servers use this liberty). I won't go further into the details of the implementation, as it is nicely described in the Developer's guide.
The other part of the library deals with HTTP requests and binds together the XML serialization code with the network protocol.
A couple of months ago I decided to organize my birthday calendar, and realized that most of the entries had a reminder, but some did not. This resulted in the suboptimal situation that I forgot some birthdays, but not all. I decided to fix this.. programmatically.
The code to do it in Scala is surprisingly simple:
package anivs
import com.google.gdata.calendar._
import com.google.gdata.data.kinds.Reminder
import Schemas._
object ChangeAnivs extends Application {
final val calName = "Birthdays"
val s = new CalendarService("test")
s.setUserCredentials("username@gmail.com", "secret")
val cal = s.getOwnedUserCalendars.find(_.title.content.startsWith(calName)) match {
case Some(bcal) => bcal
case _ =>
println("couldn't find calendar")
exit(1)
}
var link = cal.link(EVENT_FEED)
while (link.isDefined) {
val events = s.getEvents(link.get.href)
println("* got back " + events.length + " events")
addReminders(events)
link = events.link("next")
}
implicit def toOpt[T](s: T): Option[T] = Option(s)
def addReminders(events: s.eventsFeed.Feed) {
for (event <- events if event.reminders.isEmpty) {
// alert 10 min before event
val rem = Reminder(method = "alert", minutes = 10)
event.reminders = List(rem)
val e1 = s.updateEvent(event)
println("Updated event " + e1.title.content)
}
}
}
That's it! It adds a popup reminder to each event that has no reminders. Notice that the reminder uses named parameters, and the class has default values for most of its parameters (Atom has plenty of optional elements and attributes). I also added an implicit conversion from Any to Option, so that I don't need to wrap Some around the parameters I passed to Reminder.
I plan a number of improvements to the code. GData-scala-client was developed before sbt came to the scene, so I'd like to move the build from ant to sbt and publish it to the scala-tools.org maven repository. I already went through most GData-defined types and added default arguments and plan to more consistently use named parameters where possible. This should make the code much easier to understand. And lastly, I might add support for other services (currently, it supports Calendar, YouTube and Contacts) -- I'm a bit reluctant to say this too loud, though..
I managed to import some of my old posts from b2evolution. There's no custom importer for WordPress, but the RSS importer worked like a charm: even formatting looks really good (it didn't import comments, but I didn't have that many anyway). However, the RSS feed had only the most recent 10 posts or so, meaning I could not get about half of my posts. Such is life.
(I could change the size of the RSS feed in b2evolution's settings).
I finally decided to have a proper homepage, and blog from time to time. I may import some of my old blog posts, but until then I can leave you with my recent interview on jaxenter about the Scala IDE for Eclipse.
My previous blog is here.