Skip to content
Print

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.

Comments

  1. Hi,

    “For one thing, case classes cannot extend other case classes (though they can extend normal classes and normal classes can inherit from case classes).”

    A recent commit from svn:

    “r13809 | odersky | 2008-01-25 15:33:18 +0000 (Fri, 25 Jan 2008) | 1 line

    case classes can now inherit from case classes.

    Seems like that restriction will be lifted in the next release.

    Ismael Juma Monday, January 28, 2008 at 2:16 am
  2. Hi,
    “It turns out that Scala doesn’t have exception handling, at least not in the way that Java does.”
    This sentence sounds very weird to me! Whereas exceptions are handled somewhat differently in Scala than in Java, I find no way to see it in a way that could be described as “[it] doesn’t have exception handling”… The way you put it, sounds like it could be seen that way – however there’s try, catch and finally! BTW this is just a friendly observation and maybe I didn’t get your meaning :)
    Keep up the series, I’m reading them all.

    German B. Monday, January 28, 2008 at 6:57 am
  3. Neat! If only we had this sort of pattern matching in Java instead of the proposed multiple-exception catch declaration… Looks like yet another place were Scala solves a current issue in Java by providing powerful underlying flexibility instead of just adding syntax sugar for the superficial problem…

    Sun, please adopt Scala as Java 3. :-)

    Kieron Wilkinson Monday, January 28, 2008 at 9:34 am
  4. I have to say I’m not completely sold on the lack of checked exceptions. I wish the Scala guys went into more details about why they decided to do away with them in their FAQ. I imagine they make the whole functional aspect far simpler, and maybe Scala would be impossible to implement as it is with checked exceptions. On that balance, I would be happy to do without them I suppose. However, just like static type checking, they make me feel more confident in code.

    When I am working with a large code base, with complicated code execution paths, using checked exceptions (appropriately, of course ;-) ) lets me more clearly see the paths of failure at compile time. In some places, I have even added checked exceptions were they were not appropriate (shock) and then reverted to unchecked – just to to get the compiler to do some path checking for me. Having said that, that system was developed without the benefit of TDD, and it is now very hard to add. Perhaps in a more TDD-fluent system it is not so much of a problem…

    I’m trying to keep an open mind though. Scala is a completely different language after all.

    Kieron Wilkinson Monday, January 28, 2008 at 9:47 am
  5. A typo in the discussion of constructor argument extraction from the Color classes: the variable in the example code is “v” but in the text discussing it you use “x”.

    @Kieron: checked exceptions are extremely painful when working with high-order functions. While Daniel is intentionally sticking with the imperative side of Scala here, the language designers are very oriented toward functional programming in general and high-order functional programming in particular.

    A simple example: take the “List.foreach()” method. This method has a single argument which is a closure that will be executed for each item in the list. If the closure ever throws an exception, that exception will simply propagate out of the foreach() call. The List class can’t possibly know all of the exceptions that all of the closures ever passed to it could throw, so there’s no way to list the checked exceptions on the signature of List.foreach(). The only way that this can work is to have all exceptions thrown by the closure be unchecked.

    Doug Pardee Monday, January 28, 2008 at 10:37 am
  6. @Doug
    Typo fixed. Thanks for catching this!

    @Kieron
    There’s a lot of discussion around the water-cooler these days about whether or not checked exceptions are a bad idea. Theoretically speaking, they don’t really add much to the language other than enforcing some degree of documentation and a whole bunch of annoying syntax whenever a checked exception-throwing method must be invoked.

    Checked exceptions don’t really relate to static type checking. While exception *instances* are themselves types, specified thrown exceptions are not. Exceptions are technically highly-imperative control structures which allow an inversion of the call stack. Scala is quite statically typed, I can assure you. :-) Simple example:

    abstract class Color
    case class Red extends Color
    case class Blue extends Color

    val test = Red()
    test match {
    case Red => println(“red”)
    case Blue => println(“blue”)
    case _ => println(“color”)
    }

    This code will fail with a compile error at the second case statement. This is because the inferred type of “test” is Red. Since Blue is not in Red’s inheritance tree, it is not a valid pattern to use in the match. A simpler example would be:

    var a = “12345″
    a = 12345 // compiler error

    Daniel Spiewak Monday, January 28, 2008 at 1:24 pm
  7. 1 is not a prime number :)

    Michel S. Monday, January 28, 2008 at 5:20 pm
  8. It really depends on how you define it. If you say that a prime is any integer evenly divisible only by itself and 1, then 1 is in fact a prime, though a special case.

    Daniel Spiewak Monday, January 28, 2008 at 6:27 pm
  9. @Doug
    Thanks for that, I did wonder whether that was the case, but couldn’t quite visualise it. I makes sense to me now. I guess thinking functionally is the best argument I have seen for not using them.

    @Daniel
    Well, I would argue that they add a little bit to the language other than documentation or annoying syntax. :-) As I mentioned before, I like how they give some compiler checking to correct error propogation through code, which has certainly helped me dealing with complicated call-stacks like some of the code base here. However, I do agree this is a minor advantage, and as Doug illustrated, gets in the way of functional programming enough to sacrifice them.

    Hmm… I wonder if there is another way to somehow visualise that sort of thing…

    Thanks for the note about static type checking, but just to clarify, my example of static typing was purely an analogy made in respect to having confidence in code. The fact that Scala’s is strongly type checked (and seems to do it better than Java) is the only reason I am looking at it at all. :-) I think that apart from perhaps scripting, I personally wouldn’t use a dynamically-typed language by choice. Scala is the first new language I have been interested in learning for years for mainly this reason.

    Kieron Wilkinson Tuesday, January 29, 2008 at 2:06 am
  10. Daniel, very cool code boxes ! :)

    I think checked exceptions are a case of not following the “end to end argument” in system design:
    - You want thrown exception declared in (sub)system (or API) boundaries, but not necessarily in the whole stack path. The type of exception thrown also, only gets its proper meaning at (sub)system boundary.
    - You want the compiler to warn you if there are exceptions you have not treated in some well defined level that you may have annotated as not throwing “checked” exception. So as to retry, fix, log, die gracefully or do whatever you like with the exceptions right there …
    Just thinking aloud, I would not know how to implement it, but seems doable :)
    The checked exception mechanism in Java is too single-minded, cumbersome and fine grained to be properly used … So it is misused (path of least resistance), and the result is the worst, or the above mechanism is somehow implemented with non-checked exceptions but without help from the compiler.
    One sure thing I have learned since I started playing with Scala: Java has too many cases of forcing the programmer to do stuff that the compiler is best suited to do. Sometimes feels like a grumpy (but loved) old teacher …

    javier Wednesday, January 30, 2008 at 3:27 pm
  11. Something I really should have mentioned in the article is the @throws annotation:

    @throws(classOf[SQLException])
    def connect = DriverManager.getConnection(“jdbc:hsqldb:ram:testdb”, “”, “”)

    It’s not really checked exceptions, but it is a way that API developers can specify in code which exceptions a method throws.

    Daniel Spiewak Wednesday, January 30, 2008 at 3:37 pm
  12. I’ve really enjoyed reading this series, thanks.

    Going off topic, it doesn’t look like the people that work with prime numbers have counted 1 as a prime number for at least a hundred years. This is so that (for example) 12’s prime factors are always only 2, 2 and 3, not 1, 2, 2 and 3, or 1, 1, 2, 2 and 3, etc.

    This reminds me of the question of whether determiners like “the” and “many” are kinds of adjective or not, but let’s not go there.

    Carey Evans Wednesday, January 30, 2008 at 4:37 pm
  13. http://en.wikipedia.org/wiki/Prime_Number#Primality_of_one

    I stand corrected. :-)

    Daniel Spiewak Wednesday, January 30, 2008 at 4:39 pm
  14. @javier
    Thanks for that. You make some facinating points that I will have to ponder over. After playing with Scala a bit, I think the grumpy by loved old teacher is a great analogy! :)

    @Daniel
    I had previously assumed that the @throws annotation was just a compatibility thing with Java code, so I will have to look into that more, thanks.

    Kieron Wilkinson Thursday, January 31, 2008 at 1:40 am
  15. Oh it is mainly a compatibility thing with Java. Think of it like the @throws javadoc instruction and the *throws* keyword rolled into one. Scala doesn’t *force* you to catch exceptions, even those documented in the @throws annotation, but it’s still probably a good idea to do document the exceptions you throw using the annotation.

    Daniel Spiewak Thursday, January 31, 2008 at 8:28 am
  16. @Daniel, couldn’t the problem of continuations throwing exceptions be handled by having the continuation caller have variant type that include the exception statement from the continuation? It’s a slightly nasty inference problem/extra declaration problem for the compiler – but – I suspect it would be very useful. Exceptions are the one case where I feel dynamic types tend to fall down – it’s extremely hard to exception trees right in a medium to large system once it has been made, and having the compiler track this for you seems very useful.

    @Kieron, you say “I think that apart from perhaps scripting, I personally wouldn’t use a dynamically-typed language by choice.”. This reminds me of me some time back, at a time I only had experience with working with lousy implementations of dynamic typing.

    Working with Ruby and attempting to add more checking to it (see http://people.freebsd.org/~eivind/ruby/types) and thereafter working more with Perl and Java made me change my mind.

    Static typing give me fairly little, it turns out – and the extra screen real estate/reading bandwidth consumed by type declarations isn’t worth it for the scale I’ve done programming in – that is, one to a few people working on a system. Scaling from one person working on a Perl system to five people working on a Java system attempting to do the same thing lowered productivity. A lot.

    The type checking provided by a system a la Java catch very few bugs for me. Surprisingly few.

    Given this, you may be well off using a dynamically typed language for “small” development, and only switch to the statically typed stuff for large scale systems. Or maybe Scala solves the problem of expressitivity while keeping type checking – I’m going to test it out to see if it does – and in that case that’s wonderful. But, without it, static typing actually is a fairly small loss (exceptions excepted, as noted above), unless you have a quite large system. The difficult-to-detect-or-debug problems you think you’ll have – you mostly won’t (assuming a minimum of testing in place.)

    Eivind.

    Eivind Eklund Thursday, January 31, 2008 at 8:35 am
  17. @Eivind
    I do agree that the verbosity of java is a bit of a pain. However, possibly because I do work with large systems, dynamic typing is just not an option for me. It is a class of bugs I shouldn’t have to deal with, and I don’t want to deal with – even if that means typing a few extra characters (yes, and I suppose they do add up). I simply just don’t trust myself to write code that way, and I really don’t like the thought of having to write those sort of unit tests.

    I think the type inferencing in Scala is a very good solution, and playing with it a bit, I now feel that dynamically typed languages are an even more unsatisfactory way to move forward. That is not to say that Scala is perfect, but I hope that any new future languages learn from it, and see that mandatory static typing can be done without getting in the way.

    If course, that is just IMHO.

    Kieron Wilkinson Thursday, January 31, 2008 at 9:51 am
  18. Dynamic typing is actually a very lovely thing. I realize this argument is an old horse more than beaten into the ground by debates across the net, but I can’t resist. :-)

    Dynamic typing is about more than just eliminating the type declarations, it’s a totally different way of thinking about values. The canonical example of this is the so-called “duck typing”, where you write your code and don’t concern yourself with what the value *is*, but rather what it *does*. After all, why should you care if the value is a String or not as long as it properly defines the length() method? This way of thinking can be extremely nice in small scenarios.

    The problem I see with it is when you try to apply it to larger systems (as you pointed out). Things start to get a little hairy if you scale the concept upward. Having the assurance of the compiler that something is in fact a certain type not only allows static checking of certain constraints (like available methods), but also makes the code infinitely easier to reason about. When you start writing code to take advantage of the dynamic typing, things usually become more concise. However, they also become much harder to maintain simply because the logic requires more thought. It’s like the difference between a beautifully functional algorithm in LISP and the same algorithm expressed imperatively in Java. The LISP version may be shorter, more mathematically precise and possibly even more efficient, but the Java version will be far, far easier to understand.

    Scala’s type inference mechanism gives you the best of both worlds (I think). With it you lose the verbosity of type declarations, but you also can start writing code and APIs which take advantage of the inference. Specifically, coupling inference with function overloading in the API can lead to some surprisingly readable and concise code (I’ll probably give some examples of this in a future post). As you say, Scala isn’t perfect, but it’s type inference mechanism alone is sufficient reason for me to use the language.

    @Eivind
    I had never heard of your project before (adding type checking to Ruby). I downloaded the sources and starting looking through them a bit. This seems like really interesting stuff! Do you have some samples anywhere or a “getting started” tutorial I can go off of?

    Daniel Spiewak Thursday, January 31, 2008 at 11:04 am
  19. @Doug:

    Sorry, I don’t buy this explanation. I don’t see how checked exceptions and support for functional programming are mutually exclusive.

    Why not simply state that a closure cannot throw a checked exception? If the user happens to have some code that doesn’t fit this definition, they can still wrap that exception in an unchecked one and use that as a closure.

    In other words: I hope there is another justification for not including checked exceptions in Scala than the one you describe, because it is not very convincing (and overall, I tend to think that checked exceptions should be used very sparingly but also that they are invaluable to write robust code).


    Cedric

    Cedric Thursday, January 31, 2008 at 11:43 am
  20. @Eivind,

    Static typing’s main purpose is not so much to catch errors (I agree that these are few) but to allow tools to understand your code in much more depth, which in turn enables a lot of very beneficial development practices, such as:

    - Automated refactoring.
    - Easy browsing.
    - Completion.

    Equally important is the fact that statically typed code makes it easier for newcomers to read your code and understand exactly what is happening.

    These are the reasons why statically typed languages are usually seen as a better fit for “large scale” development.

    Cedric Thursday, January 31, 2008 at 11:50 am
  21. @Cedric
    If that is the case (that static typing is only to satisfy tools), then why where statically typed languages developed decades prior to the advent of modern tools such as refactoring, completion and browsing? (e.g. C has been around practically forever but browsing and completion were practically invented by Smalltalk, a far more contemporary innovation)

    Daniel Spiewak Thursday, January 31, 2008 at 11:54 am
  22. @Daniel

    Love your writing and your Scala series, and looking forward to more. Here are a few more thoughts about the dangers and limitations of Duck Typing:

    http://beust.com/weblog/archives/000269.html

    How about discussing this in a different thread, though?

    I also agree with you on the fact that type inference coupled with static typing is the best of both worlds…


    Cedric

    Cedric Thursday, January 31, 2008 at 11:57 am
  23. @Daniel,

    I’m not sure what you’re asking… do you want me to explain computer history? :-)

    If I had to venture a guess, it would be that the CPU and memory necessary to enable modern IDE’s functionalities have only started to appear in the past five years (do you remember Visual Gain and other early Java IDE’s in the late 90’s? They were extremely slow and all they provided was browsing, editing and compiling…).

    Still, this didn’t stop computer scientists from trying, and the Smalltalk IDE is a good example of an early effort in this direction (although its automatic refactoring support was close to non-existent: since Smalltalk is not statically typed, there is only so much that can be done in this area).


    Cedric

    Cedric Thursday, January 31, 2008 at 12:06 pm
  24. Right, no dispute that tools took so long to hit the scene due to computer power constraints, not due to lack of theory. What I’m saying is that static typing does not exist solely for the purpose of static analysis tools. It really is a language feature in its own right, opening up theoretical doors and possibilities for the developer that dynamic typing doesn’t allow nicely (for example, function overloading).

    Nice article btw. We probably should be discussing this in a different thread, though as I mentioned, it’s all been said already. :-)

    Daniel Spiewak Thursday, January 31, 2008 at 12:31 pm
  25. Agreed. Back then, everyone was editing their source code with vi or emacs, so tools probably had very little bearing on the design of a language.

    I can imagine the frustration of the Smalltalk inventors though: come up with such a cool IDE but having to keep it limited because the underlying language is not statically typed…

    Cedric Thursday, January 31, 2008 at 12:46 pm
  26. @Kieron, @Cedric:

    Let’s start with agreeing that if Scala and its ilk can do static typing without most of the costs, then that is a clear improvement on doing dynamic typing.

    I’ll also immediately agree that the amount of typing (number of keyboard presses) is a very minor issue. There is, however, one thing that is clearly important: How easy something is to read – and easy includes quick. This is where I find Java, C, and similar to be problematic: They add in a lot of extra tokens for type definitions, which makes Java noisy to read. There is a lot of “stuff” there that don’t really form part of the algorithm – it form part of the extra data that’s placed there to specify types.

    Kieron mention not dealing with bugs that the compiler should catch. Fair enough. I dislike dealing with bugs that the compiler should catch, as well, and I’ve worked on running static analyses on e.g. the FreeBSD kernel to catch bugs. This is clearly useful.

    There is another kind of bug that also is relevant, though: The bugs that the programmers should have seen but that weren’t seen because the code was too large, so the programmer didn’t get the context into the same page, and the bug that the programmers should have seen but didn’t because there was too much other noise (too many tokens dedicated to bookkeeping.)

    On top of this, there are the issues Cedric mention: IDE support and programmer understanding. For programmer understanding, my personal guess is that the ideal would be to declare types at the “edge” of modules, and have inference inside the modules. As for IDE support: I find that for the kind of work I do, with my primary codebase about 150kloc including the framework we maintain and associated projects dependent on the same framework bringing the total up to about 800kloc total, I don’t find this problematic. A fairly small amount of my time is spent looking up method names/signatures, and completion based on text prefixes is enough. The same with refactoring – we do it all the time, and it is fairly easy to deal with. When I worked on similar things in Java recently refactoring support was more critical, because there was more stuff that ended up bungled to start with – this seems to be due to a combination of having more junior staff working on that codebase and Java leading to larger code that needs more of the kind of refactoring an IDE can support.

    As for easy browsing: With the projects here, which actually was two implementations of more or less the same functionality in Java and in Perl, I have had the opposite experience – that the Java project in practice were much harder to browse than the Perl project. Part of this was the reliance on IDEs for browsing – for the Perl project, we didn’t do this, and ended up aggressively making the codebase browsable, with strong organization of functionality into browsable modules, with a logical directory tree around it, and using find/grep to find things if the structure wasn’t enough, also leading to developers initially getting to know the codebase well. For the Java project, the developers had relied on the IDE helping them, and had ended up with the underlying organization being such that it was hard to track down things. As a comparison data point, I regularly had the lead on the other project spend 15 minutes to find out where something was when I asked about it when I was learning the ropes there; I never spend more than a minute finding things in my own codebase, and usually only a few seconds.

    Scala’s approach to types may solve a lot of this, as the types seem very unobtrusive compared to the C/C++/Pascal/Eiffel/Java approach. The syntax isn’t so far fully to my liking – it seems a bit noisy, with a lot of use of punctuation to indicate things – but it may well grow on me. It won’t solve the problem of “Making browsing too easy makes browsing harder in practice” – the only thing I think can solve that is experienced developers (possibly experienced developers setting standards), or tools that intentionally force you to learn things during browsing.

    @Daniel: Unfortunately, I don’t have any more “getting started” guides than the documentation that’s at the top of the types.rb file (which goes through all the features with examples) – however, if there’s anything, feel free to ask by email at eeklund@gmail.com.

    Eivind Eklund

    Eivind Eklund Thursday, January 31, 2008 at 1:25 pm
  27. @Cedric: About Smalltalk IDEs: It is possible for programming environments to have access to type information even without the programmer specifying the types. There are three techniques that I can think of that does this:

    - Plain heuristics over the source code. I believe this can recover a fair amount of type information, enough so that you cover “98%” of IDE support for completion/browsing. You cannot be utterly certain of refactorings with this – but – I’ve had IntelliJ mess up refactorings in Java, too, when there’s been type weirdness, so I don’t see this as fatal, either.

    - Type feedback, that is, heuristics made from running the program. These improve on the source heuristics from above. As far as I know, these are usually used only to improve performance, yet they should be able to be used to improve IDE effectiveness.

    - Concrete type inference. There’s algorithms that recover a lot of information about the program, and even though it isn’t possible to determine all valid types in all valid programs, it is possible to determine a lot of type information in practical programs. (It would not surprise me to learn e.g. that it would be possible to recover all information in any program that would be valid Java assuming no bytecode generation.) A somewhat old reference on this topic is “Concrete Type Inference: Delivering Object-Oriented Applications (by Ole Agesen) at http://research.sun.com/techrep/1996/abstract-52.html – this include an introduction to the techniques available at that time. I am not sure if the state of the art has moved much since – I’ve not seen much activity in the area. I suspect this may be due to Smalltalk’s effective demise and replacement by Java, where the inference work is less important.

    It’s easy to conclude that static typing gives a lot – there seems to be obvious things all over the place. It is less obvious once you start looking carefully at the benefits, at which points it turns out a lot of them are “It makes it a bit easier to be a compiler/tool writer – there’s some work that’s pushed over on the programmer.” This is a reasonable tradeoff if the resources for the development of tools and compilers are very limited; the more resources are available and the larger the total scale of development moves, the more work should be pushed from the “end programmers” (where it’s done always) to the tool writers.

    Of course, as I said before, the ideal is if we can do everything statically and minimize the amount of work/cognitive noise/unnecessary barriers for the programmer using the language – static with the flexibility of dynamic except when you don’t want that flexibility and information on types available when you want it and hidden when you’re not interested – and personally I don’t know where the sweet spot is for different domains. I just know that static checking is less important to my domains than I used to think, so I’ve found the costs of static typing with the tools I’ve had available (Java, C, C++) to be too high for the static typing to be worthwhile. It’ll be interesting to see if Scala change that equation.

    Eivind Eklund Friday, February 1, 2008 at 2:55 am
  28. @article “limitations of switch/case in Java (and really any C derivative language) is that it can only be used on primitives”

    C#.

    (Many thanks for having written these articles, you are most kind for helping out the rest of us noobz.)

    Raoul Duke Friday, February 1, 2008 at 4:09 pm
  29. @Kieron

    Check http://www.artima.com/intv/handcuffs.html for the reasoning behind C#’s lack of checked exceptions. The article in that series on virtual methods is also informative http://www.artima.com/intv/handcuffs.html

    Chris Heriot Saturday, February 2, 2008 at 11:01 am
  30. @Cedric
    Another thread? Wouldn’t that mean that Daniel would have to make a post about it? I’m sure he doesn’t want to re-hash this old stuff. :)

    @Eivind
    All good points. Code readability is a good point. Personally I’m not sure that is as bad as getting rid of the typing, certainly not for well written code, but I do agree that it is something that can be a problem in Java.

    @Chris
    Thanks for that. I remember reading that article some time ago, and I remember thinking at the time that it was immensely unsatisfying. However, just in case I have changed my opinions on the matter I read it again. I still find it rather unsatisfying, but it is a good interview. I have three main problems with it:

    1) Anders says C# is neutral on checked exceptions. However, I don’t see how that is possible in the way that C# has decided (rightly or wrongly) drop them completely. It is not silent, it has made a positive move to not use them. He has his reasons, some of them are fair enough (C# has “using” which helps part of the problem), some of them are just daft (see point 3).

    2) Checked exceptions were dropped from C# without an alternative brought forward to help solve the problem. Anders said Java just moves the underlying problem elsewhere, but I think that is exactly what C# has done, except mostly reverted to the old problem (innovation, hello?). I increasingly think there is a need for something else, even if that something boils down to some sort of visualisation from some static analysis in the IDE. I for one want to know exactly what could possibly happen on a unfamiliar method I call (and Javadocs just don’t cut it, in my experience, they are just not reliable enough), especially when the source is not available.

    3) “The trouble begins when you start building big systems where you’re talking to four or five different subsystems. Each subsystem throws four to ten exceptions. [...] You end up having to declare 40 exceptions that you might throw.” That is just silly. I have no idea why he said this. Anyone who designs software like that should be shot. There are perfectly good ways to deal with this, and in my experience this has never been “a problem” – though I will that it was more difficult before exception chaining was made easier (in Java 1.4?), and that is possibly why bits of the Java API (i.e. XML) doesn’t do it very well.

    I get the feeling that some of the reasons checked exceptions get bad press is because some parts of the Java API’s use them inappropriately.

    C# is a different language to Java, and so it is up to them to decide what they want to do. I’m not saying they made the wrong decision (though I personally would feel uncomfortable without something else to replace them). However I don’t think you can just drop them from an imperative language without something else to replace them. I think Scala has a good case to drop them with its higher-order functions – that the costs far outweigh the benefits (I wish they just said that on the FAQ!). I just hope that future IDE’s visualisation techniques will take us the rest of the way.

    Anyway, it was interesting to read it again.

    Oh, btw, your second link is the same as the first?

    Kieron Wilkinson Monday, February 4, 2008 at 2:31 am
  31. @Kieron: I’ve been thinking of an alternative way of specifying checked exceptions that seems more satisfying to me. Instead of having the exceptions specified in the method header, you specify them (along with an optional conversion) at the point of call, something along the lines of:

    mymethod(a, b, c) throws WAE::ArgError

    Eivind Eklund Monday, February 4, 2008 at 3:17 am
  32. Argh – the message poster ate the last 2/3rds of my comment. I’ve replaced the syntax with something a little different, something that I hope passes without eating my comment.

    @Kieron: I’ve been thinking of an alternative way of specifying checked exceptions that seems more satisfying to me. Instead of having the exceptions specified in the method header, you specify them (along with an optional conversion) at the point of call, something along the lines of:

    mymethod(a, b, c) throws WAE::ArgError(AMS::ArgError, AMS::ArgDBMiss);

    This actually makes it obvious at the point of call what is happening with exceptions – and this is where it is important.

    Of course, for interfaces, you’d need to specify this in the method header; for normal code, the compiler should be able to infer it.

    A syntax like this makes it very easy to do exception class conversion, so the net code size might be lower than with implicit exceptions – and it also makes the code flow more obvious.

    Eivind.

    Eivind Eklund Monday, February 4, 2008 at 3:19 am
  33. @Kieron,

    I agree. I have a lot of respect for Anders and I think C# is a fine language, but his justifications for not including checked exceptions are questionable, especially because he omits the reason #1 (which he mentioned in past interviews but apparently not this one): the CLR doesn’t support checked exceptions by design because it needs to support a lot of languages that don’t have them, such as C++.

    Cedric Monday, February 4, 2008 at 8:38 am
  34. @Eivind
    That is an interesting idea. I would be nice to have something that also worked for general non-checked exceptions too though, and for those I guess your suggestion would mean there would be quite a lot to type/read?

    @Cedric
    I don’t know very much about the technical details of the JVM and CLR virtual machines, but it is interesting that Scala treats all Java checked exceptions as unchecked quite happily… Maybe that is an apples to oranges comparison.

    Kieron Wilkinson Monday, February 4, 2008 at 9:54 am
  35. @Kieron, I’d expect unchecked exceptions to not require this. With unchecked exceptions, you’d get the ability to specify conversions (as per the above), so you get some benefit – but you wouldn’t have to specify that you’re throwing to be able to throw an unchecked exception. With this simplified syntax, I suspect that we’d see a bit less unchecked exceptions, anyway, as I think there would be more benefit and less trouble with writing them checked.

    Thinking a trifle more about this, taking your comments and the comments from Anders into account, maybe a useful set of semantics would be something like:

    - You can specify a generic propagation of exceptions by just mymethod(a, b, c) throws;
    - Which exceptions get thrown are inferred over the program where possible; this means you only have to specify what exceptions get thrown for public/protected methods. It might even be reasonable to drop it for protected methods, though this requires compilation of all subclasses at the same time as the parent class to do inference.
    - If you have a finally block, you don’t need to specify what throws.

    I think this would result in net less noise, as you only specify the things that the programmer is interested in. I’m slightly uncertain about the finally block – most often, my finally blocks are written so I am sure that it will work no matter where the exception is thrown. However, it may be that it would be useful in many cases to know where things get thrown, so maybe have it be optional in some way – a la try_no_throws { … } finally { … }; vs try { … } finally { … }; – though hopefully it would be possible to invent a better syntax than that.

    Feedback very welcome. (Daniel, I hope you don’t mind that we’re using your comment system to discuss tangential issues…)

    Eivind Eklund Tuesday, February 5, 2008 at 12:37 am
  36. I don’t mind at all. It’s great getting up in the morning and having twenty pages of deep reading to get my creating juices flowing. :-)

    Just to throw my hat into the ring… Specifying checked exceptions at the call point is an interesting idea, but adding another keyword to the language complicates things. Additionally, making throws a suffix to the method call breaks with the semantic paradigms held throughout Scala’s specification. Honestly though, I’m not sure *how* call-point exception checking could be specified. Perhaps by annotating the *calling* method:

    def doSomethingBad() = {…}

    @CheckedExceptions
    def run() = {
    doSomethingBad()
    }

    Terrible syntax though, and quite inflexible. Honestly, I’m unsure how it could be done nicely at the method level.

    The class level is a different story though. Perhaps it could be specified at instantiation time that exceptions are to be treated as checked? Like so:

    val obj1 = new MyClass with CheckedExceptions
    val obj2 = new MyClass

    obj1.doSomethingBad() // throws checked exception
    obj2.doSomethingBad() // throws unchecked exception

    This is something which is actually almost doable within the existing confines of the Scala language. It would allow developers who like checked exceptions to make use of them at the cost of a slightly more verbose instantiation syntax.

    The problem with checked exceptions from a compiler standpoint is it really seems like an all or nothing proposition. Either you have checked exceptions, which means the compiler nags you if you don’t either catch the exception or add it to a throws clause, or alternatively you have no checked exceptions at all and the compiler tells you nothing. The only “middle-ground” would be having checked exceptions, but providing an inference mechanism such that if a method calls another method which throws an checked exception and does not catch it, the compiler will infer that the calling method also throws this checked exception. This is really just like the totally unchecked exceptions scenario in disguise. This polarization is why I think the checked exceptions specified on the call side may be a really great idea, just not sure what the syntax should look like. :-)

    Daniel Spiewak Tuesday, February 5, 2008 at 1:38 am
  37. Daniel,
    Your color example doesn’t compile under Scala 2.6.1. the match statement in printColor now needs to have a “case null” clause the “case _” causes an “unreachable code” compile time error. It makes sense. Given the signature of the match statement the only other case you could have would be null as the “case col:Color” handles all other valid arguments.

    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”)
    }

    Brett Knights Tuesday, February 5, 2008 at 10:27 am
  38. Thanks for catching this, Brad. I’m not sure I agree with the design decision on the part of the Scala team, but I’ll correct the sample.

    Daniel Spiewak Tuesday, February 5, 2008 at 10:03 pm
  39. @Daniel: Doing it for instantiations is an intriguing idea – unfortunately, it brings in the really serious inferred type problems, as in

    val obj;
    if (np_complete_function_checking_some_property()) {
    obj = new MyClass with CheckedExceptions;
    } else {
    obj = new MyClass;
    }

    I think it could work to do it as typing for a particular variable, though, so you’d end up with

    val obj with CheckedExceptions;

    above.

    As for inference being “unchecked in disguise”: Yes, except if you have some places where you specify that inference is not allowed. For instance, it would be natural to have the main method not allow inference – all exceptions have to be explicitly handled. Being able to specify this at other points would also be useful. I was thinking of doing this alongside a module system, where there is inference inside the module, and anything crossing module boundaries had to be explicit (or possibly explicitly declared implicit).

    WRT point of call, I would *really* like this to be at the point where a method is called, not in the header for the calling method. I feel that having to look elsewhere to understand control flow is a big mistake (just as the mistake of using reference-variables in C++ to refer to non-objects requires you to look elsewhere to understand variable modification.)

    Eivind.

    Eivind Eklund Tuesday, February 5, 2008 at 11:46 pm
  40. In your sample, type inference will blow up and give you an error (since you haven’t assigned a type to obj). Since types with specified abstract type values are subtypes of the unspecified parent (I believe), you should be able to do this:

    var obj:MyClass;
    if (np_complete_function_checking_some_property()) {
    obj = new MyClass with CheckedExceptions;
    } else {
    obj = new MyClass;
    }

    The CheckedExceptions mixin will simply modify the behavior of the value, not the type signature. Thus while it may be useful to check to see if an instance supports checked exceptions (using pattern matching on the type), it isn’t necessary nor is it the primary purpose.

    Yeah, the method header idea is pretty much bunk. :-) If it is done on point of call, it has to be somehow in the call signature itself, as you said.

    Daniel Spiewak Wednesday, February 6, 2008 at 9:43 am
  41. In 2.7.0-RC3, case classes can extend case classes, but the result is not pretty. When I write:

    case class Color(r: Int, g: Int, b: Int)
    case class Red(v: Int) extends Color(v, 0, 0)
    println(Red(3))

    what I get is:

    Color(3,0,0)

    So it seems that Scala is not even creating a class named Red. It is just creating instances of Color. Also, you can match against case Color but not against case Red. The code will not compile if you try it.

    John Simmons Tuesday, March 4, 2008 at 9:34 am
  42. John,

    Are you sure no Red class is created or is it just a bug in toString? See:

    https://lampsvn.epfl.ch/trac/scala/ticket/607

    Ismael

    Ismael Juma Thursday, March 6, 2008 at 10:29 am
  43. I am not sure what is going on, but it is very strange. Someone more knowledgeable than I about Scala needs to investigate it. I have tried to boil it down to a simple example. I created a script file redcolor.scala containing this code:

    case class Color(r: Int, g: Int, b: Int)
    case class Red(v: Int) extends Color(v, 0, 0)

    val r: Color = Red(33)
    println(r.getClass)

    r match {
    case Red(v) => println(“red ” + v)
    case _ => println(“some other color”)
    }

    //println(r)

    In this form, it prints:
    class Main$Red$2
    red 33

    If I uncomment the final println(r), I get what looks like a compile error:

    java.lang.Error: symbol variable Red$module$1 does not exist in Main.main
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:914)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.genLoadArguments(Ge
    nICode.scala:1112)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:829)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.genLoadQualifier(Ge
    nICode.scala:1059)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:826)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:416)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genStat(GenICode.scala:181)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$genStat$1.
    apply(GenICode.scala:144)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$genStat$1.
    apply(GenICode.scala:143)
    at scala.List.foreach(List.scala:763)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.genStat(GenICode.sc
    ala:143)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:940)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:441)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:941)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genStat(GenICode.scala:181)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$genStat$1.
    apply(GenICode.scala:144)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$genStat$1.
    apply(GenICode.scala:143)
    at scala.List.foreach(List.scala:763)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.genStat(GenICode.sc
    ala:143)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$bac
    kend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:940)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.gen(GenICode.scala:
    112)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$gen$1.appl
    y(GenICode.scala:70)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$gen$1.appl
    y(GenICode.scala:70)
    at scala.List.foreach(List.scala:763)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.gen(GenICode.scala:
    70)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.gen(GenICode.scala:
    134)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.gen(GenICode.scala:
    88)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$gen$1.appl
    y(GenICode.scala:70)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$gen$1.appl
    y(GenICode.scala:70)
    at scala.List.foreach(List.scala:763)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.gen(GenICode.scala:
    70)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.gen(GenICode.scala:
    80)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.gen(GenICode.scala:
    66)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.apply(GenICode.scal
    a:62)
    at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:247)
    at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:
    233)
    at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:
    233)
    at scala.Iterator$class.foreach(Iterator.scala:387)
    at scala.collection.mutable.ListBuffer$$anon$1.foreach(ListBuffer.scala:
    255)
    at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:233)
    at scala.tools.nsc.backend.icode.GenICode$ICodePhase.run(GenICode.scala:
    55)
    at scala.tools.nsc.Global$Run.compileSources(Global.scala:545)
    at scala.tools.nsc.Global$Run.compile(Global.scala:629)
    at scala.tools.nsc.StandardCompileServer.session(CompileServer.scala:137
    )
    at scala.tools.util.SocketServer$$anonfun$run$1.apply(SocketServer.scala
    :69)
    at scala.tools.util.SocketServer$$anonfun$run$1.apply(SocketServer.scala
    :69)
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:73)
    at scala.Console$.withOut(Console.scala:84)
    at scala.Console$.withOut(Console.scala:102)
    at scala.tools.util.SocketServer.run(SocketServer.scala:68)
    at scala.tools.nsc.StandardCompileServer.main(CompileServer.scala:179)
    at scala.tools.nsc.CompileServer.main(CompileServer.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at scala.tools.nsc.ObjectRunner$$anonfun$run$1.apply(ObjectRunner.scala:
    75)
    at scala.tools.nsc.ObjectRunner$.withContextClassLoader(ObjectRunner.sca
    la:49)
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:74)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:161)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
    error: fatal error (server aborted): symbol variable Red$module$1 does not exist
    in Main.main
    one error found

    John Simmons Thursday, March 6, 2008 at 3:11 pm
  44. Well, I wasn’t able to repeat your error, but I have confirmed that the following code misbehaves:

    case class Color(r:Int, g:Int, b:Int)
    case class Red(v:Int) extends Color(v, 0, 0)

    println(Red(33)) // prints “Color(33, 0, 0)”

    I’m fairly certain that this is a problem with toString() as reported in this ticket (https://lampsvn.epfl.ch/trac/scala/ticket/607). As you mentioned, getClass does in fact show that the Red class does exist, and pattern matching would be impossible without separate classes.

    Daniel Spiewak Thursday, March 6, 2008 at 4:05 pm
  45. Note that you can write:
    case 1 | 2 | 3 | 5 | 7 => true
    instead of having a line for each case.

    Seth Tisue Wednesday, April 9, 2008 at 9:35 am
  46. Ah, I didn’t know that! Very useful.

    Daniel Spiewak Wednesday, April 9, 2008 at 9:59 am
  47. Small buglet

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

    doesn’t work. It should be
    try {
    checkPrime(12)
    } catch {
    case e => e.printStackTrace()
    }

    James Iry Thursday, February 12, 2009 at 10:36 am
  48. @James

    Indeed, that is a bug, possibly a regression against an earlier version of Scala (I’m almost positive that I tested that snippet when I wrote it). I’m correcting the article; thanks for the catch!

    Daniel Spiewak Thursday, February 12, 2009 at 10:40 am
  49. To be fair, the javacode (listing 1) needn’t look too verbose:
    [code]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;
    }
    }[/code]

    Stefan Wagner Tuesday, April 28, 2009 at 12:45 pm
  50. Pardon – cut’n'paste-error, and wrong code-Tags.

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

    Stefan Wagner Tuesday, April 28, 2009 at 12:47 pm
  51. Buglet addendum: when you fixed James Iry’s buglet (with the “case e:_”) you didn’t update the surrounding text, which still refers to the “underscore” and “wildcard”. :)

    blahedo Tuesday, December 15, 2009 at 1:44 pm
  52. For some reason e.printStackTrace() does nothing in my tests. I use Scala 2.9.1 final and Java 1.6.0_25 (I think). You can see my post on a previous thread (one of the previous parts of this series) if you really think my environment is important.
    Here’s my code:
    [codeblock]
    def tryCheckPrime(n: Int) = {
    try {
    println(“tryCheckPrime(” + n + “): “);
    println(checkPrime(n));
    } catch {
    /*Catches IllegalArgumentException’s.*/
    case e:IllegalArgumentException => {
    println(“Illegal argument!”);
    /*For some reason this doesn’t work in my tests.*/
    e.printStackTrace();
    }
    /*Catches all exceptions.*/
    case _ => println(“Caught an exception!”)
    } /*finally {
    println(“Scala is great!”);
    }*/
    }
    [/codeblock]

    Dexter Thursday, March 22, 2012 at 5:16 am
  53. Oops. Obviously e.printStackTrace() won’t work in the interpreter. Just added a main method to the code in my previous post and runned it. It worked perfectly.

    Dexter Friday, March 23, 2012 at 6:31 am

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*