1

From Stateful Iteration in Python to Stateless Clojure

 2 years ago
source link: https://blog.jakubholy.net/2013/03/19/from-stateful-iteration-in-python-to-stateless-clojure/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

From Stateful Iteration in Python to Stateless Clojure

March 18, 2013
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.

Are you benefitting from my writing? Consider buying me a coffee or supporting my work via GitHub Sponsors. Thank you! You can also book me for a mentoring / pair-programming session via Codementor or (cheaper) email.

Allow me to write to you!

Let's get in touch! I will occasionally send you a short email with a few links to interesting stuff I found and with summaries of my new blog posts. Max 1-2 emails per month. I read and answer to all replies.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK