Upgrading to Clojure 1.3

13Dec11

As Nathan Marz eloquently argues, you should write even if you have no readers. So I’m starting to write again.

Here’s my notes on upgrading a fairly large project from Clojure 1.2 to 1.3.

The first step was to just change the version number and re-build. Of course, that didn’t work – I got a million warnings about dynamic variables not being explicitly declared, and eventually, there was an error complaining that I’m trying to bind a non-dynamic variable. Fair enough, the world has moved on and we weren’t looking. As most of these warnings and the error weren’t in our code, I realised that I’d have to upgrade clojure contrib as well.

Sounds simple… The problem is that, the Clojure guys have chopped it up (correctly, see Single-responsibility principle) into small bits, so you only import the ones you want. Also, many former contrib pieces are now part of Clojure core. There’s a helpful page here – http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go.

There are however many contrib libs that aren’t covered on that page, such as the unhealthy looking java-utils one. So as I’m probably going to invest a significant amount of time looking for them, I’m just going to make a note of where I found them.

The first thing worth mentioning is that as I started grepping around, it turned out many dependencies were declared but never used, or used only once, where it wasn’t really necessary and also that I found at least two whole files that I could delete completely – so this kind of exercise is always worth it, as even if it fails, you learn a lot about the code and may end up with other incidental improvements.

To begin, here’s a handy command which lists all the contrib dependencies in your project:

find . -name *clj | xargs grep contrib | grep -o "[0-9a-z\.\-]*\.contrib\.[0-9a-z\.\-]*" | sort |uniq

This page is useful too, as it shows the git repos of the new modules – http://dev.clojure.org/display/doc/Clojure+Contrib. Here’s where I found some of them:

clojure.contrib.base64 has become data.codec (Git repo: https://github.com/clojure/data.codec, Namespace: clojure.data.codec.base64, Group and artifact Id: org.clojure, data.codec, 0.1.0)

clojure.contrib.json has become data.json (Git: https://github.com/clojure/data.json, Group/artifact: org.clojure, data.json, version 0.1.2, Namespace: clojure.data.json)

clojure.contrib.except has gone – I had a couple of throw-if calls there, replaced those with assert – seems simpler.

clojure.contrib.lazy-xml -> https://github.com/clojure/data.xml, Namespace: clojure.data.xml, Group/artifact Id: org.clojure, data.xml.root., this repo isn’t ready to use yet… I figured however, that we only use one function form there, so I temporarily copied it into our code until they sort it all out.

clojure.contrib.math has become math.numeric-tower (Git: https://github.com/clojure/math.numeric-tower.git, Group/artifact Id: org.clojure/math.numeric-tower, v 0.0.1, Namespace: clojure.math.numeric-tower) – That one came with windows end-lines – funny….

Next, clojure.contrib.java-utils has gone. This post contains details – http://groups.google.com/group/clojure-dev/browse_thread/thread/b4acea9c95a9cfe9. It is a bit out of date, though, these have moved again after that. I found the best thing to do was to clone the clojure-contrib from github, checkout the 1.3.x branch and rgrep for the functions. The ones we were using from java-utils, I found in either clojure.contrib.io or clojure.contrib.string.

clojure.java.shell (and shell-out) – this is now in clojure itself, no external artifact, just require clojure.java.shell.

clojure.java.jdbc (Group/artifact: org.clojure/java.jdbc, Version: 0.1.1)

clojure.contrib.prxml – that one’s a mystery… Disappeared. I copied it from clojure-contrib into our codebase until it is available again. Noting that it’s probably wrong to use this for HTML, which isn’t strictly speaking XML.

clojure.contrib.string has gone to clojure.string – easy one.

clojure.contrib.classpath is clojure.java.classpath

str-utils, containing functions like re-split and str-join has disappeared – those functions are now largely in clojure.string – it was quite easy to change any references to those.

We had some obscure stuff being “used” – I bet every project has obsolete references remaining from either a copy/paste or things being removed/moved from a file without removing the reference. Seems that deleting code correctly is harder than writing it. And also, when you’re busy doing something like this you really appreciate the use of

(:require [x.y :as y])

over
(:use x.y)

Makes it much easier to find where that package is actually used if it is used.

clojure.contrib.zip-filter is now in clojure.data.zip (Group Id: org.clojure, Artifact Id: data.zip, Version 0.1.0, Namespace: clojure.data.zip, clojure.data.zip.xml). Note that clojure.zip is still there – that’s just zip-filter I’m talking about.

Clojure 1.3 requires dynamic defs to be explicitly indicated with ^:dynamic – that removes the warnings.

And just when I thought I was done – I wasn’t – had to upgrade Ring to 1.0.0, Compojure to 1.0.0-RC1 and Scriptjure

Next thing – the new clojure.java.shell/sh doesn’t return the command output, it returns a map, which contains the output, so I had to do (:out (sh/sh ….))

The next one was less expected, there was a clojure.lang.ILookup class, which seems to have disappeared in 1.3, I’ll just remove the type hint for the time being.

OK, there’s more – the hexadecimal literal 0x1b, is now a java.lang.Long, as opposed to java.lang.Integer in 1.2, which broke the fancy bright color console print-outs we had.

Yeay!!! It is compiling and starting up! I’m sure that other things will pop up as I go along, and I’ll try and post them. Off to do some testing…



No Responses Yet to “Upgrading to Clojure 1.3”

  1. Leave a Comment

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 )

Connecting to %s


Follow

Get every new post delivered to your Inbox.