I had a very simple function to write: given a list of timestamped objects (some having duplicate timestamps) sorted by time, modify the first object at every timestamp in a certain way.
In Ruby I might write:
prev_time = nil new_objects = objects.map do |object| result = (prev_time == object.time ? object : modify(object)) prev_time = object.time result end
But the project is coded in Clojure, which discourages such imperative code (by making it so ugly you feel silly and a little guilty for writing it). I didn’t immediately see a not-annoyingly-verbose way to implement this.
I was just failing to think functionally; if I view the problem as having:
- a function (“modify object unless it has the same timestamp as the previous one”) taking two parameters (the object and the previous one)
- a list of the objects to use for the first parameter
then this can just be solved with
map, provided we can generate a list of the values for the second parameter. Obviously they stand in a simple relationship to those for the first, so that should be easy; here, it’s just the first list, shifted to the right one position.
(defn modify-if-necessary [object prev-object] (if (= (:time object) (:time prev-object)) object (modify object))) (map modify-if-necessary objects (cons nil objects))