I love juxt . But I was reminded yesterday that not everyone has made friends with it. So, to give it a little of the limelight it deserves, I thought I’d write down My Favourite Juxt Trick.

The Recap

First, let’s recap what juxt does: it lets you pass the same arguments to several functions in a row. So if you want to find out a person’s name & height, you can do this:

( def name-and-height ( juxt :name :height ))

name-and-height is now a single function that returns both results as in a vector:

( def person { :name "Kris" :height 172 :devastating-handsomeness-factor 2 }) ( println ( name-and-height person ))

;=> [Kris 172]

Nothing special there. It’s just calling each function, :name and :height , with the same arguments, and gathering up the results.

The Trick

Now let’s do something cool with it. I’ve got a list of people working in different departments:

( def people [{ :name "Brad" :salary 27000 :department "hats" } { :name "Janet" :salary 54000 :department "capes" } { :name "Eddie" :salary 19500 :department "hats" } { :name "Frank" :salary 98000 :department "capes" } { :name "Rocky" :salary 18000 :department "shoes" }])

I’d like to roll those up by department and largesse. First let’s define what counts as highly-paid, using a number that’s entirely fictional in London:

( defn highly-paid? [ x ] ( < 30000 ( :salary x )))

Now we have two functions, and we can group by both of them:

( pprint ( group-by ( juxt :department highly-paid? ) people ))

{["hats" false] [{:name "Brad", :salary 27000, :department "hats"} {:name "Eddie", :salary 19500, :department "hats"}], ["capes" true] [{:name "Janet", :salary 54000, :department "capes"} {:name "Frank", :salary 98000, :department "capes"}], ["shoes" false] [{:name "Rocky", :salary 18000, :department "shoes"}]}

There - we’ve just built an on-the-fly, composite-key index of our data, for free.