Java to Clojure

Developer Extraordinaire Tim Washington of Interrupt Software recently gave a talk at our offices, detailing his experiences transitioning a Java app to a Clojure app. He's shared it with the Clojure Community on Google Groups. We include it here, and thank Tim for doing the talk at Jonah - very interesting!

Overview

This talk is about Clojure, and the benefits of the functional paradigm as I saw it. And this is from someone coming from the Enterprise Java world. But there's a twist. There's already a lot of technical information available to you on the web. You are all very senior people, and I won't bore you all with the details of the Clojure language itself. Instead, I thought a personal account might be more useful.

I'll give you my guiding principles for my own software craft. Then try to give a gist of how I see computing in general. This is all to give you some kind of context. Context for look at how I transformed a Java application that I created, into a much more powerful and maintainable Clojure version.

Programmer's Progress

I'm principally a web-app developer, building business process software. But really I'm passionate about technology. They key phrase I like to throw around is that I really like "extracting greater expressive power from my software tools". About 11 years ago, I began my career as a Java / OO programmer. From there, I developed an appreciation for the power of Design Patterns. The next natural steps for me were to design my own language (DSL) and do it's parser implementation. Since then, I've really began to see the expressive powers that functional programming provides. And for about the past 2 years, I've considered myself a Clojure developer. In short, I have a guiding principle of maximizing expressive power. Ideally, I want to program as quickly as I think.

Concept of Computation

What does it mean to compute? Turns out this is a complicated question. From what I can tell, to compute is an actualization (or concrete version) of a mathematical function. We are swimming in a universe of functions in math, statistics and the natural world. The lights in here are a function of certain inputs: ie, the amount of electricity and whether the switch is engaged.

I'll briefly mention what Alan Turing had to say. Then I'll briefly describe how LISPs interpreted that model of computation. What I want to setup, is an OO languages approach to computing a thing, versus a functional (or LISP) approach to computing a thing. Ultimately, this should give you some perspective on my software refactoring from OO (Java) to a Lisp (Clojure).

  • Alan Turing: Ideas of computation can be found in i) his contributions to the concept of an algorithm and ii) his description of a turing machine.
  • Algorithm: An algorithm is just a step-by-step procedure for calculations. Those steps are expressed as a finite list of well-defined instructions for calculating a function.
  • Turing Machine: This is a theoretical computer, that consumes i) an infinite ribbon of tape and ii) can perform read and write operations on the tape and iii) alters it's own state. This is a gross simplification. But the concept is that a Turing machine with the correct minimal set of operations can calculate anything that is computable, no matter the complexity (anything for which there is a function).

Object-Oriented's approach to computing: OO is actually a programming paradigm, based on what Alan Kay called the "Actors Model". This definition is derived from early versions of Smalltalk, and rules 5 and 6 show Smalltalk's Lisp heritage. Kay remarked as such, noting that rules 4-6 would mutate as Smalltalk developed.

  1. EverythingIsAnObject.
  2. Objects communicate by sending and receiving messages (in terms of objects).
  3. Objects have their own memory (in terms of objects).
  4. Every object is an instance of a class (which must be an object).
  5. The class holds the shared behaviour for its instances (in the form of objects in a program list)
  6. To eval a program list, control is passed to the first object and the remainder is treated as its message.

LISP's approach to computing: Created by John McCarthy, Lisp was originally created as a kind of practical mathematical notation. Lists were the major data structures and functions were just another value passed into a list.

  1. Probably one of the defining qualities of Lisp, is that it can be written in itself (code is data). This is what makes on-the-fly change of your running code (ie macros) possible. Basically you can think of your source file as an AST that gets loaded into the running system. And you can change that ast before it's loaded or while it's loaded.
  2. Function is a first class value in the system
  3. Recursion

Bookkeeping System in Java (OO)

I have a bookkeeping application that I originally wrote in Java. It used a custom XML/Java binding framework that I built ( like XMLBeans, but better ;) within that tool, I built an XPath interpreter to find nodes. To interact with the system, I built a shell that ran a custom language I designed. All this, with an XML database in the back-end. In retrospect, it had pretty advanced mechanisms. But the result of all that was that the system was very highly stacked, and was becoming difficult to maintain.

  • XML / Java binding framework (Bob)
  • XPath module (XPath 2.0)
  • Language Design (within Bookkeeping)
  • Custom DSL implementation (within Bookkeeping)
  • Custom Shell to run language implementation (within Bookkeeping)

Bringing in Clojure (LISP)

In 2010, I rewrote most of that bookkeeping app in about 1/10th the amount of Clojure code. First, I replaced the code that implemented the parser generated code that handled the custom languages. After a while, I realized that I didn't need XML (now spitting out to MongoDB) or that custom language (using regular functions and macros for domain specific stuff). In other words, the expressive power that I gained, and the concepts inherent in the Clojure language itself (sequences, immutable data, etc), have really altered the way I look at data processing and computing in general. I'd had some taste of functional approaches with javascript and ruby, but this was an order of magnitude better.

s-expressions (code is data) meant I didn't need XML as an extra data transfer language between my systems

  • XML / Java binding framework
  • XPath module

functions and macros removed need for a separate DSL and library

  • Language Design
  • Custom DSL implementation
  • Custom Shell to run language implementation

The original text from the discussion can be found on Google Groups at https://groups.google.com/d/topic/clojure/hcwP8x6nXLQ/discussion

Add a comment

Comment feed
The better to greet you with
No one will ever see this
Your pride and joy
The reason this comment form exists

The crew behind ASOT

We're a team of interactive, software, and business intelligence experts skilled in the design, construction, and management of online enterprise systems.

Visit The Jonah Group site

Get in touch with us