Clojure: Living Without The For Loop (1)

When you start learning languages like Lisp or Clojure, you are plunging into the world of functional programming. Functional programming, as Wikipedia explains, is closely linked to declarative programming, and this means the direct opposite of imperative programming (which includes popular languages like Fortran, Basic, C and its derivatives, Java, and many others). Declarative programming is praised as a solution for many problems of traditional programming techniques: it has a strong mathematical foundation, frees your software from side effects and simplifies writing parallel programs. So it’s definitely worth a look, but the more you read the more blurry the image gets: what does it actually mean to ‘describe’ data and their treatment? How does it feel to abandon the old first-do-this-then-do-that paradigm? And how could you ever write a loop without “for” or “while”? I will discuss these and other questions in a small series of articles.

Clojure and Quil to the rescue

We are going to write some code in Clojure in order to make programming without “for” more obvious. Dealing with functional programming is actually not that difficult because of the new rules of the game you have to learn; it’s much more difficult to give up all these beloved practices from imperative programming. Most authors of Lisp and Clojure books are trying hard to get you into the intricacies of these languages, and the beginning is hard. After a few basic principles you will notice a steep learning curve. What really makes things difficult is that most of the small programs discussed in these books are only about dealing with data: you are managing lists with applicative operators; you are descending tree structures with recursion; then you deal with lazy sequences. Even if you grasp the principles, connecting them to working code is extremely hard. Functional programming seems to float somewhere between mathematics, lambda calculus and a lot of data in a row. But how do you write a tool that processes your data at work? How do you something down-to-earth, like drawing a picture? This whole functional programming paradigm can’t be for information science nerds only, can it?

A few weeks ago I’ve discovered Matt Pearson’s great book about Generative Art. Without going too much into detail, Pearson shows how to paint both pleasing and mathematically interesting images by adding a small portion of chaos to them. His code is small, produces a lot of aha-reactions and is tremendously instructive. And they do computer graphics, so you not only have a visual feedback for your programming efforts, but you also learn a lot by playing and experimenting with that code. Which is written in Processing. Which is an imperative language based on Java. Wait a second.

Fortunately, there is a link between Processing and Clojure, and it’s called Quil. Quil is a library for accessing all the graphics power of Processing from within Clojure. Or, better said, it’s an implementation of Processing in Clojure. This enables us to take the Processing code of Generative Art and translate it into Clojure. And here we are returning to our opening question: a lot of Pearson’s imperative code is using (nested) for loops and computations. Making this code run with Clojure is an excellent exercise, because it makes us going a step further. We actually see what a range is good for, we learn how to prepare (or “describe”) data and then process them. The result is a pleasing image and a general understanding of program flow in a functional programming language.

Of course, I didn’t invent this code. The original Processing code is coming from Pearson’s book, and also the Clojure code I’m going to present here isn’t my one only, because the makers of Quil already have dedicated a lot of effort into this Processing/Clojure translation work (see their results here). I’ve learned a lot from it, but it’s no code for beginners: they have developed a lot of helper functions that are incredibly useful, but that also hide some of the program’s logic. Apart from very few exceptions I will show you code that is maybe less elegant and less performant, but that will be as close to the original Processing code as possible. The focus of this series lies on deconstructing imperative code and introducing the expressive syntax of applicative operators and how to make use of them.

I won’t include a lengthy introduction into Processing, Clojure, and Quil. I’m assuming that you already have read a few introductory chapters about Clojure and that you are looking for some ‘real’ code beyond simple examples. This series is demonstrating my recent state of knowledge about Clojure programming, so some of my opinions, recommendations, and viewpoint may change.

Before we focus on program flow, let us get a bit accustomed to producing graphics with Processing. We are skipping the common Hello World example and dive just into something more complex. This is what we want:

quil-genart-2.2.1

quil-genart-2.2.1

The Processing code looks like this:

The first line defines the window’s size in pixels, then we tell the system to use anti-alising, after that the background colour (a light grey) is defined, then brush colour and size. The two line commands draw a cross in the center of the window, a circle completes this simple drawing. (We’ll leave the drawing of a rectangle and a triangle to the Clojure part.)

So how does it look in Clojure?

Oops, that’s a bit more code, but relax. The first two lines are necessary, because Clojure code needs a namespace; line 2 says that we want to use Quil. (For instructions about how to install Quil, see here.) Just accept the last line with the -main function: this is just the program’s entry point which doesn’t do a lot here. The defsketch function is a Quil-only construct which defines the environment: here we have the window’s title, its size and the name of the “setup” function where the working code takes place. Finally.

Apart from Processing’s size command (which is part of Quil’s defsketch function) we easily recognize the original Processing code. Smooth, background, stroke and stroke-weight are direct counterparts to the respective Processing functions. The following part would be about drawing the lines, but obviously we aren’t ready yet. There’s this let block. It isn’t really necessary in this code example, but it is preparing us for future developments. This first let block defines variables that we will use later. Here they are just integer values that we are using for the line (and other commands) later: cross-size, circ-size are just integer values; x- and y-center are the result of (width) divided by 2: that’s half the width of the x-axis. Following this, y-center is half the height of the y-axis. These values are then used for computing the values for left, right, bottom, and top. All this is rather simple, but future code in this series will show more complex logic. You will learn that a lot of the program’s logic takes place in let blocks like this one, because here we are preparing data that will be processed later. The processing of these variables cross-size, circ-size, x-center and so on starts at line 22, when the first line is drawn. After that first one we draw another one, then a filled circle, then a rectangle, finally a triangle. (Yes, this is not part of the original Processing listing, but we’re here to experiment a bit, aren’t we?)

What we have learned

Clojure needs a bit of extra code to access Processing’s graphic functions. Quil has to be required, the defsketch macro defines the environment, -main is the entry point. Basic functions like smooth and background work exactly like their Processing counterparts; this is also true for real graphics functions like ellipse and rect. Preparing data happens in an initial let block (or more of them, we’ll see), and then the drawing code gets executed. This is the basic principle, our framework that we will build upon in the following parts.

So install Quil if you haven’t done so already (installing Processing isn’t necessary, because Quil brings everything with it); the next part will be a bit more challenging.

About Manfred Berndtgen

Manfred Berndtgen, maintainer of this site, is a part-time researcher with enough spare time for doing useless things and sharing them with the rest of the world. His main photographic subjects are made of plants or stones, and since he's learning Haskell everything seems functional to him.