Singing 99 Bottles of Beer With E4X (And How Mozilla Lied To Me)

How would you generate a song about 99 bottles of beer programmatically? This site holds a collection of the song in 1071 languages (and counting!) at the time of this writing. I was thinking of submitting a tail recursive implementation in JavaScript… but that’s kinda boring. Besides, the submission page says: “Your example should demonstrate the main advantages and features of the language“. Hmmm. JavaScript and tail recursion are kinda too… well-known.

And then it hit me: nobody has submitted E4X implementation of the Beer Song! E4X is one of the more interesting new features of Rhino: JavaScript for Java, which was excluded from the version of Rhino that comes bundled with Java SE 6.0. Luckily, getting E4X is not difficult. In minutes I’m ready to do my beer song.

Setting E4X In 3 Simple Steps

  1. Download Rhino here. By the way, ignore what they say about how you need xbean.jar from XMLBeans. They lied to you, you need an extra jar to get it working. I banged my head against the wall for about an hour wondering what could I’ve done wrong with such a simple line: java -cp xbean.jar;js.jar org.mozilla.javascript.tools.shell.Main, until I found out that another JAR was required. Grrr.
  2. E4X requires xbean.jar AND jsr173_1.0_api.jar from XMLBeans. You can download it here, and get the 2 JARs from the “lib” directory.
  3. Type the following command (assuming that all those 3 JARs are in the same directory):

java -cp js.jar;xbean.jar;jsr173_1.0_api.jar org.mozilla.javascript.tools.shell.Main

And you’re set. Try this out at the prompt:

js> var me = <person><name>Ray</name></person>;
js> me.name
Ray

Shweet!

Beer Drinkin’ Rhino

OK, once we’ve configured this thing, the rest is easy. Here’s the code, in it’s full glory:

var rawLyrics = readUrl(http://99-bottles-of-beer.net/lyrics.html&#8221;);

var wellFormedRawLyrics = rawLyrics.replace(/<br>/gi, “<br/>”);

var xmlLyrics = new XML(wellFormedRawLyrics);

default xml namespace = xmlLyrics.namespace();

var songVerses = xmlLyrics..*.(/^99 bottles of beer/.test(p.text()));

for each(var verse in songVerses.children()) {

var verseText = verse.text().toString().replace(“\.”, “.\n”);

print(verseText + “\n”);

}

I saved this snippet into a file, and run the following command:

java -cp js.jar;xbean.jar;jsr173_1.0_api.jar org.mozilla.javascript.tools.shell.Main -f 99BottlesOfBeer_E4X.js

to generate (or rather, rip) the full song from the 99 bottles website. Let’s hope they’ll take in my submission! 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s