From Stateful Iteration in Python to Stateless Clojure

I have a piece of Python code that leverages a stateful object and was wondering how to reimplement it in the inherently stateless Clojure, without resorting to its facilities for managing state. It turns out to be simple and beautiful.

The core of the code is a for loop that transform a list of maps, while also using input from another iterator-like object, a Palette. The Palette has the method next() that remembers the last color used and returns the next one. Here it is:

class Palette:
    last_idx = 0
    colors = ["C04000", ...]

    def next(self):
        self.last_idx = (self.last_idx + 1) % len(self.colors)
        return self.colors[self.last_idx]

graph_items = []

for idx, item in enumerate(item_maps):
    graph_items.append({
            "itemid": item['itemid'],
            "color": palette.next(),
            "sortorder": idx
            })

In Clojure, we would rather have no such state (for reasons I won’t discuss now). However, when writing idiomatic Clojure, we actually don’t need to.

We will use the fact that map – the function that can transform collection items – can take not just one but any number of collections, iterating over all of them in parallel. Instead of using the stateful palette.next(), we will create an infinite sequence of (repeating) colors and pass it into map together with the items collection. We want also the index of the items so we pass in a third sequence, the range from 0 to infinity. The map function will be thus called with (the current index, the current item, the current color).

Using infinite sequences is quite common (and elegant) in Clojure.

This is what the code could look like:

;; An infinite sequence of the colors (starting
;; again with the 1st one, when all exhausted)
(def palette (cycle ["C04000" "..."]))

(defn make-graph-items [items]
  (map
   (fn [idx item color] {"itemid" (item "itemid"), "color" color, "sortorder" idx})
       (range) items palette))

(def graph-items (make-graph-items items))

Conclusion

Statelessness is not scary. It is fun.

Disclaimer: I am only learning both Python and Clojure.

Published by Jakub Holý

I’m a JVM-based developer since 2005, consultant, and occasionally a project manager, working currently with Iterate AS in Norway.

8 thoughts on “From Stateful Iteration in Python to Stateless Clojure

  1. Very cool! I had a similar experience converting a stateful Sudoku solver from Java and Ruby to Clojure and Scala. The stateless code was easier to read (eventually) and also made it really easy to save the progression of the solution. Solving most of the 4clojure puzzles also helped me make the transition to a state-free mindset!

  2. Disclaimer: I love both Python and Clojure. however you can use an ‘infinite sequence’ style of programming quite readily in Python, too, using iterators and generators in itertools. Here is some Python equivalent to your Clojure (including lazy evaluation):
    from itertools import count, izip, cycle
    graph_items = ({‘itemid’:item[‘itemid’], ‘color’:color, ‘sortorder’:idx} for item,color,idx in izip(items, cycle(colors), count())

    1. Could you elaborate a little, please? With yield I wouldn’t need to be appending to a collection but still would need to somehow get the next color.

  3. and of course your Palette could be replaced by

    import itertools
    colors = [“C04000”, …]

    Palette = itertools.cycle(colors)

    BTW, i am a clojure love, i show this not for justifying python

    1. Nice, thanks! BTW I haven’t written this to argue that Clojure is better, only to show the transition to statelesness. Python is great.

Comments are closed.