Header

Organizing Imports in Scala

Organize Imports was a very often requested feature for the Scala IDE for Eclipse, so I wrote the first very limited version as part of my thesis. It couldn’t do much more than sorting the imports and collapsing them from multiple import statements to a single one. At the beginning of this year, Daniel Ratiu provided a patch that made Organize Imports recognize some of the unused imports.

One limitation we still had was that we didn’t really know the complete set of required imports, but this is required to, for example, replace all wildcard imports with the actually used ones. Another request was that it should be possible to push import statements down to the scope where they are used. For this, we also need to know which parts of the code require which imports.

Yet another motivation to write some code to analyze dependencies was that I want to provide a move refactoring, and for this too we need to know some of the dependencies in the code. But that’s for a future post, back to what we have now:

As you can see, just like the JDT, we can now configure grouping for imports (groups are separated by a blank line), and it’s possible to expand or collapse imports from the same package. The Scalaz or Lift users will likely want to always use wildcard imports on some packages and types, so this is also possible. The JDT has some additional options, but I think I implemented the important ones.

And there’s more! No, not Reversi, but if there are missing imports in the file, Organize Imports will add them for you:

This all is part of the latest beta release of the Scala IDE, so please give it a try and open a ticket if you find a problem.

2 comments »
Header

Eliminating Pattern Matching

In the last few years, I worked on several Java projects where we transformed and analyzed abstract syntax trees, so when I started learning Scala, pattern-matching quickly became one of my favorite language features. I could never warm up to the visitor pattern, so I was thankful that Scala offered a much more powerful alternative.

What I also liked very much was Scala’s consistent use of the Option type in its standard library. Now, instead of having to read the documentation to find out whether some call could return null, the type checker forced me to handle this where necessary. So a lot of my early Scala code looked as follows:

doSomething() match {
  case Some(value) => Some(doSomethingElse(value))
  case None => None
}

While it’s still possible to get a NPE in Scala, it just doesn’t happen with well-written libraries, simply because there’s no need to ever use null.

(By the way, isn’t it funny that Java forces you to check exceptions but doesn’t help you with the much more common and annoying null problem?)

So yes, in practice, Options do save you from NPEs. Does your code also get smaller (because usually, in Scala it will)? Not if you pattern match on Some/None, all the un-wrapping and lifting is quite verbose.

Nowadays, certainly influenced by all the discussions on monads, I realize that pattern-matching on Option is a very primitive form of abstraction, and instead of the code above I now write:

doSomething() map (value => doSomethingElse(value))

(For those unfamiliar with functional programming, map applies the function to the value inside a Some, and does nothing when called on a None.)

Even better, we can fully automate this refactoring! I’m currently working on a first version in the scala-refactoring library. So far, I’ve implemented the refactoring for map, but there are many more we can do, for example:

  • If the Some case does not construct a Some but calls a function that returns an Option, we use flatMap instead of map.
  • If the Some case evaluates to Boolean and the None case returns false, we can replace it with exists. If Some returns true and None returns false, we can just replace the whole pattern match with isDefined.
  • When the None case is (), we can transform to foreach.

So far we have only looked at Option, but there is more: for example, we could also replace pattern-matching on lists and recursion with folds. I’m sure somebody has already written a paper about such refactorings, but I haven’t found anything yet.

What do you think about eliminating pattern matching? Do you also prefer mapping to explicit pattern-matching?

18 comments »
Header

Plans for 2011

I originally wanted to write a review of 2010 here, but by now I definitely missed the deadline for year-end-retrospectives, so I’m going to make this about my plans for 2011.

I’ve spent a large portion of last year on the Scala Refactoring project, and I’m quite happy with the results: four editors/IDEs are using the library to do refactoring, plus others use parts of it to manipulate or generate Scala source code.

It’s clear that I cannot continue investing as much time into it as during my master thesis (except of course, if someone would be willing to sponsor me ;-) ). My plan for this year is to find at least half a day per week to continue writing new refactorings and improving the existing code. One idea I originally had with the refactoring library hasn’t played out yet: getting others to create new refactorings. It’s really not that hard! So give it a try if you have an idea for a refactoring you want to automate.

Besides working on the refactoring library, I also really want to get back to writing for InfoQ. Speaking of InfoQ, I’m looking forward to QCon London in March!

Now, enough with the blogging – there are some bugs in Organize Imports I need to fix :-) A happy new year to all of you!

No comment »
« Older