Flag This Hub

Build your own Clojure toolkit

By


In any programming language there are going to be chunks of code you want to reuse often. That's the whole point of programming languages, really; if you never reused anything you might as well program in machine code (you can think of the language itself as a collection of libraries to gloss over the repetitive things going on at the hardware level). A good language will encourage you to build up your own suite of similarly handy tools; a poor one will make this awkward enough that copy/paste seems like the lesser of evils.

Clojure, and Lisps in general, strongly encourage "bottom-up" programming to complement the more traditional top-down design cycle: as you discover features that you wish were included in the language but don't really belong to your specific problem domain, you design generic tools that bolster the language itself, making it more suited to the sorts of things you tend to do with it. Paul Graham really says it better than I ever could:

In Lisp, you don’t just write your program down toward the language, you also build the language up toward your program. As you’re writing a program you may think “I wish Lisp had suchand-such an operator.” So you go and write it. Afterward you realize that using the new operator would simplify the design of another part of the program, and so on. Language and program evolve together. Like the border between two warring states, the boundary between language and program is drawn and redrawn, until eventually it comes to rest along the mountains and rivers, the natural frontiers of your problem. In the end your program will look as if the language had been designed for it.

If the above snippet interests you, either because it sounds useful or because it's gorgeous writing, you really should read On Lisp: it is full of such gems and I'm only a third of the way through it myself. If it doesn't interest you, there is probably something wrong with you but you can still benefit from writing your own generic libraries.

The problem

But if you're like me, you hack on multiple projects at once, and it often doesn't seem worthwhile to write a utility in project A if you only use it once in project A. After a while you end up wanting it in project B, and so maybe you write it as an actual utility this time, and use it in B. Then you want to use the same tool in C, but it's not there so you have to copy the tool definition from B to C, and now if you ever improve the utility you have to maintain the code in at least two places; probably more places if it's really a useful generic tool.

I did this for a while, especially with a couple debugging tools - because Clojure's in-built debugging facilities are not nearly as good as those available for Common Lisp or Java. But it was a hassle, and left me with a lot of copies of the same code. Then the other day I realized it's not at all hard to carry these tools around between projects because of how easy Clojure makes distribution of libraries.

Source: Apache software foundation

Java to the rescue?

I don't have that much experience with Common Lisp, so what I'm about to say is probably false: distributing libraries with Common Lisp is not trivial. Even Paul Graham, in his chapter on the value of utilities and code reuse, says that for very small utilities it may be easier to just rewrite them.

But because Clojure is hosted by Java, it has access to the vast ecosystem of Java libraries, including those for distributing libraries. In particular, the Clojure build tools lean on Apache Maven for dependency management and distribution. Further, clojars is a free, "world-writable" Maven repository for hosting Clojure libraries that aren't mature enough to make it to Maven central.

So I realized I could just define my toolbox as an independent project, distribute it via clojars, and then declare that my other projects depend on it. Now whenever I make any fixes or additions to my utilities, I can simply increase the version number and push a new version out. My other projects depend on "at least version 0.1.0", so I can merely re-resolve dependencies to get the newest version.

Be a first-class participant

Partly because it's so new, my own utilities library isn't really that interesting, though it's at https://github.com/amalloy/amalloy-utils if you want to have a look anyway. Following cemerick's lead, the top-level namespace for my tools is "amalloy". Even now it feels pretentious: am I so interesting as to merit a namespace to myself? No, not really, but who cares? I just want a way to distinguish my utility package from his, and so far nobody else wants to use the amalloy name. I recommend that you do something similar, but feel free to do anything you like. The important thing is that you put your utilities on the Net and stop writing them over and over in every project. It's not hard to get a clojars account, and once you have one you can push to it as simply as "cake release" or "lein push".

None of this is at all revolutionary: "Of course you can make your code publicly available", you may say. And indeed it seems pretty obvious now, but I've been using Clojure for nearly a year, and it only occurred to me a few days ago. Hopefully I've found some readers who haven't realized this yet, and whose code will be improved by following this advice. Feel free to leave links to your own utilities in the comments, if you like: it will be nice to see the impact I've had, and I'm sure either I or some other reader will find some reason to start using your tools too!

Comments

No comments yet.

Submit a Comment
Members and Guests

Sign in or sign up and post using a hubpages account.



    Like this Hub?
    Please wait working