Jakub is a Java EE developer since 2005 and occasionally a project manager, working currently with Iterate AS. He's highly interested in developer productivity (and tools like Maven and AOP/AspectJ), web frameworks, Java portals, testing and performance and works a lot with IBM technologies. A native to Czech Republic, he lives now in Oslo, Norway. Jakub is a DZone MVB and is not an employee of DZone and has posted 149 posts at DZone. You can read more from them at their website. View Full User Profile

From Stateful Iteration in Python to Stateless Clojure

03.25.2013
| 3471 views |
  • submit to reddit

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 at DZone with permission of Jakub Holý, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Liam Knox replied on Mon, 2013/03/25 - 8:07am

I think could do better not touching these loose cannon languages.

Clojure is an interop mess that will never get any great hold

Python is equally flawed.

Sure you can learn something from Lisp but it is clear that Lisp is not ever. ever going to give Jobs.  OO is still the bread winner. FO helps you do better code.

Rolf C Stadheim replied on Mon, 2013/06/24 - 3:28pm in response to: Liam Knox

Python is Object Oriented.

And if you think Clojure interop is a mess, I doubt you have done some interop between any language at all, Clojure has almost seamless interop with Java. I know, I use it every day.

Calling Python or Clojure for "loose cannon" languages is ridiculous... 



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.