Thursday, September 20, 2007

Scala Alert: bootclasspath/a Considered Canadian

Author's Note: Please forgive what is, essentially and unfortunately, a very bad pun. It's late, and I've had a long week, what with my Automata exam coming up and all. And, for the record, I have nothing against Canadians. James Gosling is Canadian. So is William Shatner. I once lived in Vancouver. Please don't hate.

So I was looking at bin/scalac and bin/scala, the Scala toolset equivalents of javac and java, and I found myself learning some stuff. For instance, scala (which executes a Scala, um, executable) is simply a shell script that sets a bunch of shell/environment variables and finally runs this command:

${JAVACMD:=java} ${JAVA_OPTS:=-Xmx256M -Xms16M} -Xbootclasspath/a:"$BOOT_CLASSPATH" -cp "$EXTENSION_CLASSPATH" -Dscala.home="$SCALA_HOME" -Denv.classpath="$CLASSPATH" -Denv.emacs="$EMACS" scala.tools.nsc.MainGenericRunner "$@"

This points out some interesting interestingness. First off is: Scala executables are ultimately run by...java! Or what passes for it on your system. Pretty neat, huh? Although it makes total sense if you think of java as the command that starts up a JVM on some arbitrary .class file, not the command that runs a Java(TM) language program.

(Author's Other Note: Scala code gets compiled to JVM-compliant bytecode. Which is proof that real closures are theoretically possible in Java(TM). Although they are not likely to happen in your lifetime. But I digress.)

Second off is: buried amongst the options to java is the non-standard -Xbootclasspath/a:"$BOOT_CLASSPATH". Unlike plain ol' -Xbootclasspath, this option lets you append some arbitrary jars to the regular bootclasspath (hence the /a). In this case, what it appends is $SCALA_HOME/lib/scala-library.jar if it exists, which gives the executable access to the Scala standard library. Which includes among other things the package that implements Scala Actors.

P.S.: It turns out there's also a -Xbootclasspath/p, which stands for "prepend", but is not as funny when applied to Canadians.

P.P.S.: I like the option to provide a default value for some environment variable that may not exist on a given system (e.g., ${JAVACMD:=java}).

P.P.P.S.: EMACS??? What the heck does that have to do with running a Scala executable? Time for some more research, eh?

Friday, September 07, 2007

Recommended Reading: The Linguist

Do yourself a favor: start reading The Linguist, by Steve Kauffman, who speaks 9 languages and founded thelinguist.com as a resource for those who want to learn a new language. I particularly like the following quote, from the entry Why children learn languages better than adults:
Children have not yet been converted from naturally curious language explorers into teacher-dependent grammar learners.

I took Spanish for three years in high school (Hola, Srta. Chambless!), and I was very fortunate that my teacher taught the class in Spanish, and required us to participate by speaking Spanish. After the first six weeks of the first year, no English was allowed, and precious little during that time. It was brilliant. It forced us to learn Spanish the way kids in Spanish-speaking families learn it - by experiencing it and figuring things out, not by sitting at a desk with a vocab list and a dictionary.

I've often wondered why no one has developed a computer language training curriculum modelled after some of the more effective human language training methods. But that's beside the point of Kauffman's thesis above. Ultimately, we learn what we love. And we love what we find out for ourselves as the result of exploring the things we find interesting, not what is hammered into us by some random instructor.

Friday, August 17, 2007

Scala: The Next Next Java!

Yeah, yeah. I know. It's only been recently that Erlang has started being touted as "the next Java". I just thought I'd get a jump on crowning the next next Java. Oh, sure, no one gets to officially be The Next Anything without a Pragmatic Bookshelf book backing it, but I'm sure it's just a matter of time before a Scala book is announced.

After all, Scala shares a lot of the advantages of Erlang -- principally, its support for Actor-based concurrent programming and hence its powers of super-scaling. But it also has a secret weapon that Erlang doesn't have: it runs on the JVM! Yes, that JVM! It also has access to the multitudinous multitudes of existing Java libraries out there, making for a (potentially) easier migration path.

No need to wait for Java 7 (or (possibly much (much)) greater) for closures in Java! Write some Scala scaffolding around your existing Java classes and have them today!

Le roi mort! Vive le roi!

Thursday, August 09, 2007

The Good, The Snide, and The Ugly (More on Autoboxing)

Wow. You know you've hit the big time when famed Java geek author Norman Richards gets all snarky on your sh*t. I would like to point out, though, that I never said autoboxing was "evil". I just said it was !cool. And no amount of Richards' sarcastic aping of my (deliberately) satirical-yet-lighthearted take on it is going to convince me otherwise.

The problem, of course, lies in the fact that, pre-autoboxing, there was no question of an assignment to a variable of type int throwing an NPE. For the first 87% of Java's numerical-version-life you just couldn't do it. The concept had no meaning, like the questions "what is north of the North Pole?", or "what color is up?". Or "can I borrow your copy of 'XDoclet in Action'?" (Author's note: because no one in my office has one).

Pre-autoboxing, Eclipse would have flat out disallowed the assignment of an Integer to an int. And here's the important point: Eclipse would have disallowed it, because the compiler would have disallowed it. Because you couldn't assign an object reference to a primitive type, inadvertently or advertently. It wouldn't be a legal assignment, so it wouldn't compile, so there would be no way for it to throw an NPE in production. That's what static typing is supposed to ensure.

In true famed Java geek author style, though, Richards totally misses the pedagogical point when he uses as his sarcastixample the potential NPE-ness of code that deals with String. Which is an object type. Which has since the beginning of Java time been subject to NPE's. As opposed to primitive types. Like int. Which have not. Until autoboxing rocked our world and broke static typing.

I've actually been waiting for someone to snark on my (deliberately) satirical-yet-lighthearted insinuation that I rely too much on my IDE. That was the first point I took away from this whole exercise, and believe me I will be more wary in the future. I'm pretty sure I'm not the first to be burned by such an over-reliance. But in this case, even if I were using Emacs and the command line, I would still have fallen victim to this problem. The fault lies in the language, not in my reliance on any tool.

Bottom line: I don't think it should be too hard to excuse someone who, when seeing an NPE in his stack trace, doesn't leap immediately at the assignment to the int variable.

But maybe that's just me.

Tuesday, August 07, 2007

Autoboxing == !Cool

So you're finally getting used to the idea of Java 5's "feature" of converting between primitive types and their corresponding object wrappers (e.g., int -- Integer). You're getting to the point where you kind of trust it. You're even getting to the point where you kind of rely on it. Life is good.

Then you go too far and try something weird and exotic like, oh, I don't know:

int sucker = thisMethodReallyReturnsAnIntegerNotAnInt();

No squiggly red line in your Eclipse editor. Cool! That must mean this will work! Because Java has static typing, and you can count on that! Yea you!

The problem is, it will work. It will work very nearly all the time. It will work until your method returns a null instead of an actual Integer. At which point you'll get a NullPointerException buried in your Struts 2 / OGNL / JSP project's Eclipse console stack trace, followed by a two-hour detour into the debugger wondering what the heck is going on. I mean after all, your code compiled, right? It worked for the first hour, right? Static typing is good, right? Autoboxing works, right?

Not that you're bitter.

Monday, July 09, 2007

Starting up a VPS on Slicehost

Author's Note: None of the following is intended to portray any of the companies named in an unflattering light. There were good things about all of them, along with the not-so-good. They all have their fans and their detractors. However, you know that phrase we geeks use when talking about our experiences with things technical? YMMV? Well, my mileage varied, considerably. To the point where I changed vehicles.

My first experience with running Rupp Consulting Services, LLC on VPS (Virtual Private Server) was with Rimuhosting. This was after some, shall we say, sub-optimal experiences with, in chronological order, Yahoo!, Textdrive, and Dreamhost. I went to VPS primarily to relieve the pain of memory/resource constraints/contention, and the inevitable shared downtime that comes with running a shared server.

Rimuhosting, I must say, were great about functionality and support. I left them only reluctantly, having decided to farm out my email and my blog to Google, and not seeing the need to pay for my web presence. Well, that lasted about a month, and I've decided to jump back in. I considered going back to Rimu, but something I read on a blog convinced me to give Slicehost a shot. So far I'm glad I did.

For $20/month, I get root access to my very own "slice" with 256MB memory, 10GB storage, and 100GB bandwidth/month. This compares to 96-128MB / 4GB / 30GB bandwidth on Rimu for the same price. You have to move up to Rimu's $40 plan to even get close to these specs (224MB / 4-8GB / 60GB). So space and bandwith are not a problem. However I do expect to bump up against my memory limit once I start doing any serious Rails development, which is my primary reason for getting back in the VPS game.

One of the reasons for this post, in fact, is to document some of the extra work I had to do to get Ruby and Rails going once my slice was up and running. First, I followed the instructions here to lockdown logins and SSH ports and stuff.

This is one of the first chances Slicehost had to shine. You see, I stupidly locked myself out after the last step (installing the iptables firewall). Slicehost provides an Ajax-based console for just such an occasion. Unfortunately, that wasn't working for me (note to self: enable cookies in Safari next time!), so I needed an even more drastic solution: rebuilding my slice. Fortunately, I was only backing out 10 minutes of work, so this was a viable option. Again, Slicehost really shines here by letting you rebuild automatically from an option on their management screen. A few clicks of the mouse and five minutes of waiting and I got to start fresh, this time being more careful with iptables and actually proofreading my changes and stuff. Amazing what that will do.

Then it was on to installing Ruby, et al. The yum package manager is your friend here. I considered downloading and building everything from source, but that takes a lot of time, and I'm actually becoming a fan (thanks to MacPorts on my home machines) of the whole package management concept. So a quick yum install -y ruby got me started.

Apparently, though, Slicehost installs a very slimmed-down version of Fedora, as I discovered when I tried to yum install -y rubygems. I had problems with missing libraries, which I was able to cure with yum install -y ruby-devel. Which exposed some other missing goodies. Rinse, lather, repeat.

Long story short, here's what I ended up having to yum install to be able to build native extensions for gems and do other *nix hackery I'm used to being able to do out of the box:
  • wget
  • make
  • which
  • tar
  • gzip
  • gcc
I've also installed nginx (vice Apache), mongrel, subversion, and mysql - the usual suspects. nginx works as advertised, and one Mongrel instance handles my Mephisto-generated site traffic nicely. Just that, though, is enough to get me close to 200MB, and that's without the Trac instance I plan to install later. So I may be upgrading my plan even sooner than I expected.

Wednesday, June 27, 2007

On the Importance of Being Multi-Lingual

My day job is currently focused on porting an Eclipse RCP ("Rich Client Platform") Java application -- essentially a WORA desktop app -- to a Struts2/JSP/Hibernate webapp. We're using a fair amount of JavaScript (via Prototype and Scriptaculous, along with some home-grown code) for the things you'd normally use JavaScript for. Nothing out of the ordinary there.

One of the home-grown JavaScript bits that I've been working with recently is a text-box filter. You type in the text you want to filter on in a text-box, and the table rows (or li's, or what-have-you) that don't contain that text get hidden, leaving only those that pass the filter. Again, pretty standard stuff.

The fun started when I wanted to add the ability to filter not just on text, but on a time range chosen from a dropdown menu, like, say, "show me only the results that were posted within the last two hours". I wanted to re-use the existing filter code as much as possible, because a lot of it is exactly what I need, but I needed a way to specify comparing two times (the time of each post versus the time range selected) instead of the default behavior of checking for a match on the input text.

(Author's Note: Those of you who are familiar with Ruby probably already know exactly where I'm going with this. Bear with me while I build the suspense a little longer).

If the filter were written in Java (pre-closures Java, anyway <wink/>), I would have no choice but to jump through some serious refactoring hoops -- implement the new behavior, probably as a new set of methods, and then add in some way to designate which behavior I wanted either by introspecting on my arguments, or by an explicit switch, or...yuck. And if I were only aware of Java idoms, there would be nothing stopping me from taking the same approach in JavaScript.

Fortunately, I spent the bulk of last year doing some serious Ruby programming, which forced me to get used to the idea of blocks. Equally fortunately, I've taken some time to get familiar with idiomatic JavaScript programming, and learned that functions are first-class datatypes in JavaScript, which means they can work pretty much like blocks do in Ruby.

And so I was able to solve my problem with minimal impact to the existing codebase, by adding a parameter to the constructor (an optional block/function, defaulting to the existing "match" behavior), and making the code that does the actual filtering call that anonymous function rather than explicitly calling "match". One optional parameter and one (tiny) layer of indirection later, and I've got a solution that will never need extending again. The next time I come up against a type of filter that I haven't already implemented, I can do so on-the-fly, by building a function that implements the exact comparison behavior I want and passing it to the generic filter.

Do yourself a favor: stop hating on Ruby because you're irritated by all the attention it gets. Stop assuming that if you learn idiomatic Ruby you're going to have to turn in your "Java ROOLZ, Ruby DROOLZ" badge and your "I (heart) static typing" secret decoder ring. Free your mind, and the rest will follow. And whatever other inspirational pop lyric you care to apply here.

Learning another language (doesn't have to be Ruby; could be Python, or Lisp, or Erlang, or Scala, or...) can only increase your problem-solving capability. And, after all, isn't that what we're all about? Solving problems?