Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Clojure: See Every Step of a Reduce

DZone's Guide to

Clojure: See Every Step of a Reduce

· Java Zone
Free Resource

Microservices! They are everywhere, or at least, the term is. When should you use a microservice architecture? What factors should be considered when making that decision? Do the benefits outweigh the costs? Why is everyone so excited about them, anyway?  Brought to you in partnership with IBM.

Last year I wrote about a Haskell function called scanl which returned the intermediate steps of a fold over a collection and last week I realised that I needed a similar function in Clojure to analyse a reduce I’d written.

A simple reduce which adds together the numbers 1-10 would look like this:

> (reduce + 0 (range 1 11))
55

If we want to see the intermediate values of this function called then instead of using reduce there’s a function called reductions which gives us exactly what we want:

> (reductions + 0 (range 1 11))
(0 1 3 6 10 15 21 28 36 45 55)

I found this function especially useful when analysing my implementation of the Glicko ranking algorithm to work out whether a team’s ranking was being updated correctly after a round of matches.

I initially thought the reductions function was only useful as a debugging tool and that you’d always end up changing your code back to use reduce after you’d solved the problem but I realise I was mistaken.

As part of my implementation of the Glicko algorithm I wrote a bit of code that applied a reduce across a collection of football seasons and initially just returned the final ranking of each team:

(def initial-team-rankings { "Man Utd" {:points 1200} "Man City" {:points 1300}})
 
(defn update-team-rankings [teams year]
  (reduce (fn [ts [team _]] (update-in ts [team :points] inc)) teams teams))
> (reduce update-team-rankings initial-team-rankings (range 2004 2013))
{"Man City" {:points 1309}, "Man Utd" {:points 1209}}

I realised it would actually be quite interesting to see the rankings after each season for which reductionscomes in quite handy.

For example if we want to find the rankings after 3 seasons we could write the following code:

> (nth (reductions update-team-rankings initial-team-rankings (range 2004 2013)) 3)
{"Man City" {:points 1303}, "Man Utd" {:points 1203}}

Or we could join the result back onto our collection of years and create a map so we can look up the year more easily:

(def final-rankings
  (zipmap (range 2003 2013) (reductions update-team-rankings initial-team-rankings (range 2004 2013))))
> (get final-rankings 2006)
{"Man City" {:points 1303}, "Man Utd" {:points 1203}}

Discover how the Watson team is further developing SDKs in Java, Node.js, Python, iOS, and Android to access these services and make programming easy. Brought to you in partnership with IBM.

Topics:

Published at DZone with permission of Mark Needham, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}