Upgrading to Clojure 1.3
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…
Filed under: Uncategorized | Leave a Comment
No Responses Yet to “Upgrading to Clojure 1.3”