Tuesday, October 16, 2007

Fun With Scala: Things I'm Learning From Lift #1

So I'm starting somewhere around the very beginning with the Liftweb framework: LiftServlet.scala, which is in the net.liftweb.http package. This looks like Lift's answer to a Rails controller, or a Struts Action (Author's Note: probably with some caveats that I haven't found yet; (pleasant) comments welcome if I'm wrong about this).

Fun Thing #1: The very first import is
import javax.servlet.http.{HttpServlet, HttpServletRequest , 
HttpServletResponse, HttpSession}

How's that for interoperability with Java? I haven't gotten that far yet, but this tells me that whatever Lift uses for its request/response implementation is going to conform to the usual Java interfaces. And how do you like the syntax for this style of import? I like it a lot, because it lets you do the equivalent of:
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
...et cetera...

...on a single line (it's a single line in the original source; I've split it here for friendlier rendering). Without resorting to importing everything in the http package with a wildcard. This way you get to see exactly what you need. Yeah, I know a good Java IDE will manage the imports for you, so it's not as much of a pain as it used to be, but I like the compactness of this syntax. As it happens, the current version of the Scala plugin for Eclipse doesn't have the equivalent of "Organize Imports", so this syntax is definitely a boon.

Fun Thing #2: There's a syntax for importing not just classes, but members of a class. Like so:
import net.liftweb.util.Helpers._

This basically says "make everything in the Helpers class (actually it's a singleton object, but think of it as a class for now) available to this class without my having to qualify it with 'Helpers.' all the time".

For example, there's a bit of code in LiftServlet that goes like this:
val md = parseInternetDate(mod)

This makes it appear that parseInternetDate() is defined in the LiftServlet class. But it's not. It's defined in Helpers. If you're used to modules/mixins in Ruby, this should seem very familiar to you. If not, now might be a good time to get used to them, because they're way cool.

Fun Thing #3: No, the lack of semicolons at the end of the code samples is not a typo. The Semicolon is Dead! Long Live the Semicolon! No, scratch that -- Long Live Scala!


David Pollak said...

Thanks for sharing your exploration of lift. Looking forward to your feedback as to how we can improve lift. Also, as you do blog posts, please announce them to the lift list.



Ken said...

Those look like pretty mundane features of Scala to get excited about! ;) I'm looking for where Scala is significantly better than Java for something.

#2 is possible in Java 5:

import static net.liftweb.util.Helpers.*;

David Rupp said...

@ken: Just getting started, dude! Although, I have to admit, it doesn't take much to excite me. ;-)

David Rupp said...

@ken: After a little research, it looks like the Java 5 import works only for the static members of a class. Which is a start, I guess, but it lacks the full power of mixins/modules as in Scala and Ruby.

To quote Yoda: "Impressed I am not."

Ken said...

The example you gave maps exactly to Java's static import. Imports just make it so you can refer to something without specifying a namespace. I see in the Scala intro that it can do mixins, but that's totally different. Please post an example of that if you find a good way to use it.

It sounds like you are building a real app with Scala. Is this for work or pleasure? I'm anxious to see how it goes.

Eelco Hillenius said...

Scala has great features, but #2 isn't something that would warm me up. But I'm not crazy about Java 5's static imports either (and I know very few people who are actually). It makes code only harder to follow imho.