Here's how I would do it: ``` (defn to-timed-events [events] (->> events (reduce (fn [[acc-events acc-time] {:keys [duration], :as event}] [(conj acc-events (assoc event :time acc-time)) (+ acc-time duration)]) [[] 0]) first)) ```
A few comments: 1. Usually, if you're reaching for explicit recursion in Clojure, consider using `reduce` instead. It's rare to find a problem that can't be expressed more succinctly with `reduce`. 2. As another rule of thumb, if you're unsure how to model a sequence transformation in Clojure, chances are that `reduce` is what you're looking for. This is especially true if you're coming from an imperative background, where people are not used to think in terms of reduce/fold. 3. The step function needs to keep track of both the events seen so far and the time of all previous events added together. This "accumultator" value -- the first argument to the step function -- holds the intermediate result of the computation so far. 4. Because we need to keep track of two things (events and accumulated time), the initial value passed to `reduce` is a pair (vector with two elements). We use sequence destructuring to access both elements easily in the step function. 5. We don't care about the accumulated time at the end. So we discard it in the final step by extracting the events from the result using `first`. On Sun, Apr 24, 2016 at 12:01 PM, Olivier Scalbert <oli.sc...@gmail.com> wrote: > Hi all, > > I am a Clojure beginner .... > And I have an advice to ask ! > > I have an array of events: > > (def events [ > {:id "1" :duration 100} > {:id "2" :duration 200} > {:id "3" :duration 300} > ]) > > I wanted to transform this array into: > [ > {:id 1, :duration 100, :time 0} ; event 1 starts at 0 > {:id 2, :duration 200, :time 100} ; event 2 starts when event 1 is > finished, so at 100 > {:id 3, :duration 300, :time 300} ; event 3 starts when event 2 is > finished, so at 100 + 200 > ] > > Here is the function code: > > (defn to-timed-events > ([time events] (to-timed-events time [] events)) > ([time timed-events events] > (if (empty? events) > timed-events > (let [current (first events) > next-time (+ (:duration current) time)] > (recur next-time (conj timed-events (assoc current :time time)) > (rest events)) > )))) > > It seems to work, but it looks a bit long for what it is doing. Is it > possible to improve it ? > > Thanks for your help, > > Olivier > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.