Skip to content

Adding Type Checking to Ruby

6
Feb
2008

What’s the first thing you think of when you consider the Ruby Language?  Dynamic types, right?  Ruby is famous (infamous?) for its extremely flexible type system, and as a so-called “scripting language”, the core of this mechanism is a lack of type checking.  This feature allows for some very concise expressions and a great deal of flexibility, but sometimes makes your code quite a bit harder to understand.  More importantly, it weakens the assurances that a certain method will actually work when passed a given value.

Several different solutions have been proposed to workaround this limitation.  The canonical technique involves intensifying tests and increasing test coverage.  Ruby has some excellent unit test frameworks (such as RSpec) which serve to ease the pain associated with this approach, but no matter how you slice it, tests are a pain.  Having to rely on tests to take the place of type checking in the code assurance process can be extremely frustrating.

Another, less common technique is to simply perform dynamic type checks within the method itself.  Like so:

def create_name(fname, lname)
  raise "fname must be a String" unless fname.kind_of? String
  raise "lname must be a String" unless lname.kind_of? String
 
  fname + " " + lname
end

This code explicitly checking the dynamic kind of the parameter values to ensure that they are of type or subtype of String.  The issues with this sample should be relatively obvious.

Primarily, it’s ugly!  This sort of repetitious, boiler-plate conditional checking is exactly the sort of thing Ruby tries to avoid.  What’s more is the added bulk of all of these repetitive checks (assuming you perform one check per-parameter per-method) because far more unwieldy than just improving the rspec test coverage.

While manually type checking may be a bad solution syntactically, it’s on the right track conceptually.  What we really want is some sort of assertion that the parameters are of a certain type, but that won’t overly bloat our existing code.  We need some sort of framework that will “weave in” (think AOP) its type assertions without getting in the way our our algorithms.

Well it turns out that someone’s already done thisEivind Eklund kindly pointed me to his type checking framework in a comment on a previous post.  The basic idea is to perform the type checking assertions, but to factor the work out into an API encapsulated by an intuitive DSL.  So rather than performing all those nasty unless statements as above, we could simply do something like this:

typesig String, String
def create_name(fname, lname)
  fname + " " + lname
end

It’s really as simple as that.  Passing the type values to the typesig method just prior to a method declaration give the cue to the Types framework to perform some extra work on each call that method.  Now we have the runtime assurances that the following code will not work (with a very intuitive error message):

create_name("Daniel", 123)

Will produce the folling output:

ArgumentError: Arg 1 is of invalid type (expected String, got Fixnum)

But the fun doesn’t stop there.  Ruby encourages the “duck typing” pattern, where algorithm developers concern themselves not with what the value is but rather what it does.  This means that the type checking really should be done based on what methods are available, not just the raw type.  It turns out that the Types framework supports this as well:

class Company
  def name
    "Blue Danube"
  end
end
 
class Person
  def name
    "Daniel Spiewak"
  end
end
 
typesig String, Type::Respond(:name)
def output(msg, value)
  puts msg + " " + value.name
end
 
c = Company.new
p = Person.new
 
output("The company name is: ", c)
output("The person is: ", p)
 
output("The programmer is: ", "a genius")    # error

Types can check not only the kind of the object but also to what methods it responds.  This is crucial to enabling its adoption into modern Ruby code bases, many of which rely heavily on this “duck typing” technique.

You can think of the Types framework just like another layer in your testing architecture.  Obviously it’s not performing any sort of static type checking (since Ruby has no compile phase).  All it’s doing is providing that extra certainty that you’re never passing something weird from somewhere in your code, something that would break your algorithm.

So what’s the catch?  Well, obviously you need to have the Types framework installed.  It’s not as easy as just typing gem install types either, since the framework actually predates Ruby Gems.  You’ll have to download the framework and then copy around the types.rb file yourself.  But this is just deployment semantics.  The more interesting issue are the limitations of the code itself.

As far as I can tell, the only restriction on the framework is that it must be used within a proper class, not in the root scope.  This means that all of my examples above would have to be enclosed in a class, rather than just copy-pasted into a .rb file and run in place.  But other than this one limitation, the framework is incredibly flexible.  I really haven’t shown you the seriously interesting stuff in terms of the API (there are more examples at the top of the types.rb file).  In many ways, Types is actually more powerful than any static type checking mechanism could be (yes, I’m even including Scala in that evaluation).

I haven’t had a chance to use Types on any serious project myself, but I can see tremendous potential, particularly for companies with large-scale Ruby/Rails deployments or even smaller projects looking for just a bit tighter code assurance.  As far as I’m concerned, there shouldn’t be a non-trivial Ruby project attempted without this lovely library, Rails or no Rails.

Scala for Java Refugees Part 5: Traits and Types

4
Feb
2008

One of the mantras repeated throughout this series has been that Scala is Java, just better.  Thus it stands to reason that Scala would at a minimum support all of the features and power that Java offers.  So far you’ve seen things like object-oriented constructs, the power of methods and even dabbled a bit with pattern matching.  Through all this, I’ve deliberately avoided a particularly obvious Java construct: interfaces.

Interfaces (or are they?)

Scala doesn’t have any direct analogue to Java’s interfaces.  This answer may seem a bit surprising, given what I’ve been saying about similarity to Java.  The fact is that Java’s interfaces are really a very weak mechanism and a paltry imitation of their forebear: multiple inheritance.

Back in the days of C++, when the power of the dark side waxed full, object oriented languages commonly had support for inheriting from more than one superclass.  In C++, you could see this in examples like the following (shamelessly stolen from Wikipedia):

class Person {
public:
    virtual Schedule* get_schedule() const = 0;
};
 
class Student : public Person {
public:
    Student(School*);
 
    Schedule* get_schedule() const {
        return class_schedule;
    }
 
    void learn();
 
private:
    Schedule *class_schedule;
};
 
class Worker : public Person {
public:
    Worker(Company*);
 
    Schedule* get_schedule() const {
        return work_schedule;
    }
 
    void work();
 
private:
    Schedule *work_schedule;
};
 
class CollegeStudent : public Student, public Worker {
public:
    CollegeStudent(School *s, Company *c) : Student(s), Worker(c) {}
};

Looks fairly standard right?  The question comes when you call the get_schedule() function on an instance of CollegeStudent?  Think about it, what should happen?  Should you get a class schedule or a work schedule?

The answer is that nobody knows.  This is called the diamond problem and it’s something which annoyed computer scientists to no end in the early days of OOP.  Of course one solution to the problem is to just never use multiple inheritance.  Unfortunately, this becomes extremely restricting in certain situations which really call for the feature.

Java’s designers recognized the need for multiple typing (e.g. CollegeStudent is both a Student and a Worker), but they wanted to avoid the issues associated with inheriting conflicting method definitions along multiple paths.  Their solution was to design the interface mechanism, a feature which allows multiple typing without the complications of multiple inheritance.  So in Java you would represent the above sample like this:

public abstract class Person {
    public abstract Schedule getSchedule();
}
 
public interface IStudent {
    public void learn();
}
 
public interface IWorker {
    public void work();
}
 
public class Student extends Person implements IStudent {
    private Schedule classSchedule;
 
    public Student(School school) {...}
 
    public Schedule getSchedule() {
        return classSchedule;
    }
 
    public void learn() {...}
}
 
public class Worker extends Person implements IWorker {
    private Schedule workSchedule;
 
    public Worker(Company company) {...}
 
    public Schedule getSchedule() {
        return workSchedule;
    }
 
    public void work() {...}
}
 
public class CollegeStudent extends Person implements IStudent, IWorker {
    public CollegeStudent(School school, Company company) {...}
 
    public Schedule getSchedule() {...}
 
    public void learn() {...}
    public void work() {...}
}

Holy long examples, Batman!

If the sheer verbosity of the example wasn’t enough to convince you of its flaws, direct your attention to the CollegeStudent class.  We’ve achieved our primary goal here of creating a class which is both a Student and a Worker.  Unfortunately, we had to implement the learn() and work() methods multiple times.  Also, we complicated our hierarchy by a factor of two and introduced the much-despised IRobot convention.  Finally, our hierarchy is less constrained than the C++ version in that there’s nothing to prevent us from creating workers which are not people.  Logically this makes sense, but our specification says that all students and workers should be people, not insects or computers.  So we’ve lost flexibility, been shouldered with verbosity and introduced redundancy, all in the attempt to avoid a trivial logical disjunction.

Traits

Scala recognizes that interfaces have their issues.  So rather than blinding creating a reimplementation of the same problems found in either Java or C++, Scala takes a new approach.  Inspired by a combination of Java’s interfaces and Ruby’s mixins, the designers of Scala have created the trait construct.

trait Book {
  def title:String
  def title_=(n:String):Unit
 
  def computePrice = title.length * 10
}

Scala’s traits are quite nice in that they can not only define abstract members, but also full method definitions.  At the same time, they allow inheriting classes to inherit from more than one trait.  They pass on their type information and implementations to their children, as well as enforcing the abstract members.  At first glance, this seems like it would be just as bad as straight-up multiple inheritance, but it turns out the problems have been mitigated in some very clever ways.

To start with, there’s that ever-annoying override keyword.  I mentioned back in the article on basic OOP that any method which overrides a method in a superclass must be declared with the override modifier.  At the time, I likened it to the language mandating the use of the @Override annotation, with its primary purpose being to enforce the good practice.  The keyword however serves a far more important purpose, as we’ll see in a second.

The real key to the power of traits is the way in which the compiler treats them in an inheriting class.  Traits are actually mixins, not true parent classes.  Any non-abstract trait members are actually included in the inheriting class, as in physically part of the class.  Well, not physically, but you get the picture.  It’s as if the compiler performs a cut-and-paste with the non-abstract members and inserts them into the inheriting class.  This means that there’s no ambiguity in the inheritance path, meaning no diamond problem.  We can rewrite our CollegeStudent example in Scala without redundancy or fear of paradox:

abstract class Person {
  def schedule:Schedule
}
 
trait Student extends Person {
  private var classSchedule:Schedule = ...
 
  override def schedule = classSchedule
 
  def learn() = {...}
}
 
trait Worker extends Person {
  private var workSchedule:Schedule = ...
 
  override def schedule = workSchedule
 
  def work() = {...}
}
 
class CollegeStudent(school:School, company:Company) extends Student with Worker {
  // ...
}

Now if we make a call to the schedule method on an instance of CollegeStudent, the compiler knows that we’re referring to the implementation of schedule in the Worker trait.  This is because Worker was mixed in after the Student trait.  We could just as easily reverse the order and make the Student implementation the dominant one:

class CollegeStudent(school:School, company:Company) extends Worker with Student {
  // ...
}

Now Student#schedule is the dominant implementation while the implementation in Worker is overridden.  This is where the override keyword becomes extremely useful.  It’s sort-of the last stop fallback to ensure that no ambiguities sneak into the hierarchy without glaring compiler errors.

The absolutely most important thing to notice in the example, aside from the multiple-inheritance, is that CollegeStudent is actually a proper sub-type of Person, Student and Worker.  Thus you can operate on an instance of CollegeStudent polymorphically as an instance of one of these super-traits. In fact, other than the whole mixin thing, Scala traits are pretty much just like abstract classes.  They can declare abstract members, non-abstract members, variables, etc.  They can even extend other classes or traits!  The one catch is that Scala traits cannot accept parameters in their constructor.

This means that in one sense, the C++ version of our CollegeStudent snippet is more powerful than the Scala translation.  In Scala, the Student and Worker traits cannot have constructor parameters, so there’s no way to specify a School or Company as part of the inheritance.  If you ask me, it’s a small price to pay for all of this power.  And no matter which way you slice it, traits are still far more flexible than Java interfaces.

Type Parameters

You may not have realized this, but Scala is a statically typed, object-oriented language.  There are many such languages (C++, Java, etc), but they all have a common problem: accessing instances of a specific type from within a container written against a supertype.  An example serves better here than an explanation:

ArrayList list = new ArrayList();
list.add("Daniel");
list.add("Chris");
list.add("Joseph");
 
String str = (String) list.get(0);

The last line requires the cast because although we know that list only contains String(s), the compiler doesn’t know it.  As far as the compiler is concerned, it’s just a list of Object(s)From the beginning though, this has been a problem for Java.  It has lead to mountains of ugly code and nasty casts to try and trick some type-safety into generic contains.  Enter type parameters.

Java 5 saw the introduction of a feature called “generics”.  Just about every other language calls them “type parameters”, so I tend to use the terms interchangeably.  Java’s generics allow developers to specify that an instance of a generic type is specific not to the supertype but to a specific sub-type.  For example, the above example rewritten using generics:

ArrayList<String> list = new ArrayList<String>();
list.add("Daniel");
list.add("Chris");
list.add("Joseph");
 
String str = list.get(0);

Not only have we avoided the cast on the final line, but we have also added type-checking to all of the add() invocations.  This means that the compiler will only allow us to add String instances to the list.  This is quite nice of course, but it has its limitations.

Because Java 5 was striving to maintain backward compatibility with old code-bases, the generics implementation isn’t as flexible as it could be.  Most of this inflexibility stems from the decision to implement generics using type erasure, rather than reified types.  However, there are other issues which make working with Java generics weird, such as the incredibly cryptic and inconsistent syntax.  In short, Java generics are a language afterthought, whereas Scala type parameters were designed into the language from day one.

Scala type parameters have a lot of nice things going for them.  Perhaps number one on the list is a more consistent syntax.  Rather than a generics-specific wildcard character ( ? ) and an overloading of the extends keyword, Scala type constraints utilize operators and meta-characters which are consistent with the rest of the language.  But I’m getting ahead of myself…

This is how the list example might look translated into Scala:

val list = new ListBuffer[String]
list += "Daniel"
list += "Chris"
list += "Joseph"
 
val str = list(0)

Passing over the operator overloading ( += ), the important thing to notice is the syntax of the ListBuffer type parameter.  You’ll notice that Scala uses square brackets rather than greater-than/less-than symbols to denote type parameters.  This is a bit counter to the traditional syntax (handed down from C++), but it turns out to be quite clean and powerful.  Here’s a simple, parameterized class:

class MyContainer[T] {
  private var obj:T = null
 
  def value = obj
  def value_=(v:T) = obj = v
}
 
val cont = new MyContainer[String]
cont.value = "Daniel"
 
println(cont.value)

With the exception of the square brackets, the syntax is remarkably similar to Java’s.  Unlike C++, there’s no weird template typing; no mind-numbingly verbose method prefixing.  Just solid, clean code.

Now Java allows generics to implement type constraining, which forces the type parameter to satisfy certain conditions.  (extending a certain supertype is a common example)  This can be accomplished easily through Scala, and as I said before, without overloading a keyword:

import scala.collection.mutable.HashMap
 
import java.awt.Component
import javax.swing.JLabel
 
class MyMap[V<:Component] extends HashMap[String,V]
 
val map = new MyMap[JLabel]
map += "label1" -> new JLabel()
map += "label2" -> new JLabel()

In the class MyMap, the single type parameter must be a subtype of Component, otherwise the compiler will throw an error.  This of course is specified using the <: operator, rather than the extends keyword as it would be in Java.  This has two advantages.  1) it avoids overloading the definition of a basic keyword, and 2) it allows for lower type bounding without unintuitive constructs.

Lower type bounding is when the type parameter is constrained such that a certain type must inherit from the type parameter.  This is accomplishable in Java, but only by doing some extremely weird rearranging of the generic definition.  In Scala, it’s as simple as switching the direction of the type constraint operator:

class MyMap[V:>CollegeStudent] extends HashMap[String,V]

In this declaration, type parameter V can be any type which is extended by CollegeStudent (from our earlier example).  Thus the parameter could be Student, Worker or even Person.  Obviously, this is a lot less useful than specifying an upper type bound, but it still has applications, especially in some of the core Scala classes.

Just like Java, Scala allows type parameters on methods as well as classes:

def checkString[A](value:A):A = {
  value match {
    case x:String => println("Value is a String")
    case _ => println("Value is not a String")
  }
  value
}
 
val test1:String = checkString("Test Value")
val test2:Int = checkString(123)

As you can see, Scala extends its type inference mechanism to type parameters similar to how Java does.  I could just as easily have left the explicit type declarations off of the two values and Scala would have properly inferred the types from the return types of the corresponding checkString() invocations.  This is of course very similar to how Java allows method type parameter inference (see the Arrays#asList(T…) API).

Again much like Java, Scala allows explicit specification of method type parameters.  For example, this is the unsafe idiom to cast objects in Scala (the “sanctioned” syntax is to make use of pattern matching):

val obj:Object = "Test String"
val str:String = obj.asInstanceOf[String]

Here we are explicitly specifying String as a type parameter to the asInstanceOf method.  This method returns an instance of class String generated from the instance of class Object in the obj value.

In truth, we’ve barely scratched the surface of the capabilities of Scala’s type parameter mechanism.  If you’re looking for some brainf*ck of an evening, I suggest you read up on Scala type variances.  If there was any doubt that Scala is a more powerful language than Java, it will be quickly dispelled.  :-)

Oh, as a side note, Scala type parameters are currently (as of version 2.6.1) not quite compatible with Java generics.  While you can use parameterized Java classes, specifying the type parameters using the Scala syntax (e.g. new ArrayList[String]), you cannot actually declare parameterized Scala classes to be usable from within Java.  According to the mailing-lists however, the next release of Scala will indeed have full cross-compatibility between Scala and Java in the area of type parameterization.

Conclusion

The deeper we go in the Scala language, the more we realize the truly awesome power of its syntax.  What’s really amazing though, is that the designers were able to create a language with such flexible constructs without sacrificing the underlying clarity and consistency of the syntax.  At first blush, Scala continues to look a lot like Java and remains extremely readable to the average developer.  Somehow this clarity is retained without coming at the expense of capability.  Traits and Scala’s type parameters are just one more example of this fact.

Coming to you in the sixth and final installment: a few steps into the wonderful world of Scala-specific syntax.

Databinder Gets ActiveObjects Support

2
Feb
2008

Nathan Hamblen (otherwise known as n8han from Coderspiel) has been putting a lot of work recently into his persistence interop framework, Databinder.  Interestingly enough, some of this work has involved ActiveObjects.  Nathan has taken some of the code I did for the wicket-activeobjects module, adapted it to Databinder and enhanced it 10 fold.  As of right now in the Databinder SVN, it is possible to achieve complicated interaction between your Wicket views and the ActiveObjects database model without any undo hassle. (announcement)

For those of you who don’t know, Databinder can be thought of as a compatibility layer between Wicket and Hibernate.  The idea being to smooth some of the rough spots that can lead to extensive boiler plate when using Hibernate and Wicket together for an application.  Yes, I know there’s a wicket-extras project which has the same goal, but in my opinion, Databinder does it better.  Databinder acts as a completely natural layer between Wicket and Hibernate, not between you and either of the two frameworks.  This means that you can write code naturally which uses Wicket and write vanilla-standard Hibernate code without any framework weirdness introduced by Databinder.  In short, the framework does precisely what it needs to when it needs to and stays out of the way for the rest of the time.

Anyway, there’s not much more I can say about the framework, it really speaks for itself.  I’ll I can tell you is that if you’re using Wicket and ActiveObjects together without Databinder, you’re really missing out.  ActiveObjects integration is included in the unreleased version 1.2, currently only obtainable directly from the SVN.  So fire up your SVN client (svn://databinder.net/databinder/trunk), run off a Maven build and get hacking!

Scala for Java Refugees Part 4: Pattern Matching and Exceptions

28
Jan
2008

So far, we’ve been examining the similarities between Scala and Java.  Areas where Scala syntax is so similar to Java’s as to be almost identical.  Of course, this doesn’t take full advantage of the language, but it allows developers to utilize the cleaner Scala syntax within the restrictions of a familiar environment.  From this point on, things are going to get a bit weird.

A number of the “more advanced” features in the Scala language are clear departures from Java.  They may mirror the corresponding Java feature, but in syntax the concepts are totally different.  Among these “different features” is the concept of pattern matching, something critical to the understanding of exceptions.

Pattern Matching

As is oft parroted on the blogosphere, pattern matching in Scala is really a lot like Java’s switch/case construct.  So in Java, one might write something like this:

public boolean checkPrime(int number) {
    // checks if a number between 1 and 10 is prime
    switch (number) {
        case 1: return true;
        case 2: return true;
        case 3: return true;
        case 5: return true;
        case 7: return true;
 
        default: return false;
    }
}

It’s obviously an extremely naive prime number sieve (if you can call it that), but it demonstrates the example quite effectively.  This familiar usage of switch/case is basically just a shortened if/else block.  One could just as easily have written this as a series of if statements, however it would have been less concise.  Interestingly enough, switch/case is often discouraged in object-oriented languages in favor of cleaner architectures making use of polymorphism for the same result.  But I digress…

One of the major limitations of switch/case in Java (and really any C derivative language) is that it can only be used on primitives.  You can’t use switch/case to test a String, for example (a need which arises more often than one would think).  In fact, the most complex type testable within switch/case is the Enum, and even this is just being reduced to its ordinal values under the surface.  In short, switch/case is a very crippled hold-over from the dark ages of #include and extern.

Fortunately, the designers of Scala chose not to include this “feature” in their new language.  Instead, they implemented a “new” (it’s actually been around in other languages for a long time) concept called pattern matching.  At a basic level, it allows algorithms which are very similar to the checkPrime(int) example:

def checkPrime(number:Int):Boolean = {
  number match {
    case 1 => return true
    case 2 => return true
    case 3 => return true
    case 5 => return true
    case 7 => return true
 
    case _ => return false
  }
}

Looks a lot like the Java example, right?  The biggest difference which likely jumps out at you is the lack of a default statement.  Instead, we see the return of Scala’s ubiquitous wildcard character, the underscore.  Literally read, this example means: match the value within number; in the case that it is 1, return true; in the case that it is 2, return true; …; for any previously unmatched value, return false. 

Scala case statements can’t “overflow” into each-other (causing multiple matches) like Java’s can, so even if we weren’t returning values, the algorithm would still be safe.  In fact the method can be more concisely expressed as follows:

def checkPrime(number:Int) = number match {
  case 1 => true
  case 2 => true
  case 3 => true
  case 5 => true
  case 7 => true
 
  case _ => false
}

This works because the match statement actually returns whatever value is returned from the matched case statement.  This allows match/case algorithms to be far more “functional” in nature, actually improving readability (as in the above example).

Now if this were the end of Scala’s pattern matching capabilities, it would still be worth using.  However, Scala’s capabilities go far beyond mere integer comparison.  For example, Scala’s match statements are not restricted to “primitive” types (which Scala doesn’t have, incidentally).  You can just as easily perform pattern matching on strings or even more complex values.  For example, the instanceof operation in Scala looks like this:

var obj = performOperation()
var cast:Color = obj match {
  case x:Color => x
  case _ => null
}

In Java of course we would do something like this:

Object obj = performOperation();
Color cast = null;
if (obj instanceof Color) {
    cast = (Color) obj;
}

The Scala example may look a bit odd, but trust me when I say that it’s really quite elegant.  In the example, we’re actually performing pattern matching against the type of the input.  If the type matches, then the case-local variable x is populated with the value from obj and assigned type Color.  This variable can then be returned from the match, and thus assigned to cast.  If no type is matched, just return null.  Scala allows a great deal of power in its pattern matching in that it allows the implicit assignment of case-local variables based on the matches.  In the example given, x is implicitly assigned iff (if and only if) the matched value is of the given type.

Case Classes

Now type matching may be cool, but once again it fails to encompass the awesome power afforded by Scala’s match statement.  Not only is Scala capable of inspecting the type it is matching, but also values within that type.  This probably doesn’t make much sense, so once again we resort to code samples:

case class Number(value:Int)
 
def checkPrime(n:Number) = n match {
  case Number(1) => true
  case Number(2) => true
  case Number(3) => true
  case Number(5) => true
  case Number(7) => true
  case Number(_) => false
}
 
checkPrime(Number(12))

The first statement is the key to the whole thing: defining a new case class “Number” with a single property.  Case classes are a special type of class in Scala which can be matched directly by pattern matching.  The also have some other attributes such as a compiler-defined toString(), a proper equivalency operation and so on.  You can also create a new instance of a case class without the new operator (similar syntax to instantiation in C++).  But in every other respect, case classes can be treated identically to normal classes. 

Scalists (is that a word?) like to use case classes in situations where they need a “quick and dirty” class, due to the predefined operations and the conciseness of its instantiation syntax.  I personally don’t care for this convention, mainly because case classes have some odd corners which can bite you when you least expect.  For one thing, case classes cannot extend other case classes (though they can extend normal classes and normal classes can inherit from case classes).  More importantly, case classes become implicitly abstract if they inherit an abstract member which is not implemented.  This can lead to some very strange looking compiler errors when attempting pattern matching on what you thought was a valid hierarchy.

Anyway, back to our example.  For each case, we’re actually creating a new instance of Number, each with a different value.  This is where the significance of the case class instantiation syntax comes into play.  Scala then takes our new instance and compares it with the one being matched (and this is all type-checked by the way).  Scala sees that the instances are the same type, so it introspects the two instances and compares the property values (in this case, just value).  Now this would seem to be massively inefficient, but Scala is able to do some clever things with case classes in pattern matching and everything turns out nicely.

Everything seems sort of intuitive until we reach the final case, which is using our friend the underscore.  Of course we could have just written this as the “any case” (case _) but I wanted to demonstrate wildcards in case classes.  This statement basically means “match objects of type Number with any value”.  This is the case which is matched by our checkPrime(Number(12)) invocation farther down.  Oh, and as a side note, if null is passed to this function, Scala will throw a MatchError, proving once again the loveliness of the Scala type system.

Of course, this sort of matching doesn’t seem very useful.  All we did was encapsulate an Int within a case class.  While this is cool for illustrative purposes, it would be grounds for execution if seen in a real code base.  This is where the power of inheritence meets case classes.

class Color(val red:Int, val green:Int, val blue:Int)
 
case class Red(r:Int) extends Color(r, 0, 0)
case class Green(g:Int) extends Color(0, g, 0)
case class Blue(b:Int) extends Color(0, 0, b)
 
def printColor(c:Color) = c match {
  case Red(v) => println("Red: " + v)
  case Green(v) => println("Green: " + v)
  case Blue(v) => println("Blue: " + v)
 
  case col:Color => {
    print("R: " + col.red + ", ")
    print("G: " + col.green + ", ")
    println("B: " + col.blue)
  }
 
  case null => println("Invalid color")
}
 
printColor(Red(100))
printColor(Blue(220))
 
printColor(new Color(100, 200, 50))
printColor(null)

The output will look something like this:

Red: 100
Blue: 220
R: 100, G: 200, B: 50
Invalid color

There are a couple of important things about this example.  Firstly, you should notice that we’re heavily using the feature in pattern matching which allows us to assign new values as part of the match.  In each of the specific color cases (Red, Green, Blue) we’re passing an undefined variable v to the new case class instance.  This variable will be assigned the property value of the class if a match is made.  So for our first invocation, the matcher finds that we’re looking at an instance of Red.  It then retrieves the property value from the instance (red) and assigns that value to the local case parameter x.  This value is then usable within the definition of the case.

The second thing which should jump out at you is the use of polymorphic case classes.  Here we have several specific types of Color which each take a single value as their property.  This value is then passed to the super-constructor (along with a number of literal values, depending on the color).  Red, Green and Blue are all case classes, Color is not.  We can’t just say case Color(r, g, b) => because Color is just an ordinary class, it cannot be matched in such a fashion.

This pattern is also the first we have seen with a multi-line case.  Technically, this is still just a single expression (a scope) which itself contains multiple expressions, but you can still think of it like a switch statement with multiple statements prior to a break.

Finally, if nothing else applies, the instance will match case null and print our “Invalid color” message.  You’ll notice we did no explicit null checking, we just let the matcher handle the ugly details for us.  Now isn’t that clean?

Case classes are about the closest thing Scala has to Java’s enumerations.  Oh Scala does have a type Enumeration that you can do interesting things with, but idiomatically case classes are almost exclusively used in situations where enumerated values would be employed in Java.  This of course lends itself to greater flexibility (because case classes may contain values) and better “wow factor” when showing off your code.  :-)

Exception Handling

Well I’ve been promising all along that I would somehow tie this in with exceptions and the time is now.  It turns out that Scala doesn’t have exception handling, at least not in the way that Java does.  Instead, Scala allows you to try/catch any exception in a single block and then perform pattern matching against it.

Let’s take our checkPrime() example.  It really only handles integers between 1 and 10, so it would be quite nice to test this precondition and throw an exception if it fails.  We can do this quite trivially:

def checkPrime(n:Int) = {
  if (n < 1 || n > 10) {
    throw new IllegalArgumentException("Only values between 1 and 10")
  }
 
  n match {
    case 1 => true
    case 2 => true
    // ...
  }
}

Not very interesting from a theoretical standpoint, but it’s a solid piece of code.  You can see that Scala’s exception throwing syntax is almost identical to Java’s.  In fact, the only real difference between Scala’s exception dispatch and Java’s is that Scala does not have checked exceptions.  It’s not very apparent in this example, but we could have just as easily thrown an instance of java.lang.Exception or some other “checked” exception, without modifying our method signature.  Scala also does not force you to catch exceptions, it trusts that you’ll clue in when your program crashes.

So how do we invoke this method, pedantically watching for exceptions?  It turns out that the syntax looks surprisingly like pattern matching:

try {
  checkPrime(12)
} catch {
  case e:IllegalArgumentException => e.printStackTrace()
}

You see the catch clause is actually a match statement under the surface on any exception thrown by the body of try.  The catch runs through and matches against the various cases and finds our IllegalArgumentException rule.  Once again, we’re implicitly creating a new local variable within a pattern.

If we wanted to catch all exception types, we could resort to our old friend the underscore:

try {
  checkPrime(12)
} catch {
  case _ => println("Caught an exception!")
}

This syntax seems to really only lend itself to a single catch block, rather than Java’s concept of a different catch for each exception type.  But since catch is really just a pattern matching block, it seems obvious that we don’t really need more than one catch block, we can just handle different exception types as different cases:

import java.sql._
import java.net._
 
Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:testdb", "sa", "")
try {
  PreparedStatement stmt = conn.prepareStatement("INSERT INTO urls (url) VALUES (?)")
  stmt.setObject(1, new URL("http://www.codecommit.com"))
 
  stmt.executeUpdate()
  stmt.close()
} catch {
  case e:SQLException => println("Database error")
  case e:MalformedURLException => println("Bad URL")
 
  case e => {
    println("Some other exception type:")
    e.printStackTrace()
  }
} finally {
  conn.close()
}

Since Scala doesn’t actually have checked exceptions, we really could get away with not catching the MalformedURLException (since we know that it’s correct).  However, it’s worth showing the multiple-exception scenario just for the sake of example.

This example also shows use of the finally block, something which should be quite familiar to any Java developers.  In Scala, the finally works precisely the way it does in Java, so there should be no concerns about odd behavior when designing code which requires it.

Conclusion

Scala exceptions are fairly intuitive beasts.  They behave almost exactly like Java’s (with the exception of being all unchecked), providing a familiarity and an interoperability with existing Java libraries.  The exception handling mechanism however demonstrates considerably more power, making use of Scala’s built-in pattern matching capabilities and thus maintaining a far more internally consistent syntax.

The next article in our series will delve a little deeper into the hidden mysteries of Scala’s type system: traits and type parameters.

[RESOLVED] Problems in the Main Feed

23
Jan
2008

To those who were affected by the recent problems in the RSS, you have my sincere apologies.  It seems that the WP-SuperCache plugin doesn’t work nicely with PHP in safe mode (thanks to the How-To Geek for turning me on to the solution).  Since MediaTemple switched it’s GS service over to PHP in safe mode recently, there wasn’t much of a precedent to go off of when debugging.

Anyway, the supercache has been disabled (just relying on wp-cache now) and the feed seems to have been stable for a while now.  Once again, I apologize for force-feeding you invalid XML!