I have been coding in Clojure for 5 years now - but still from time to time I am re-discovering some interesting functions from the clojure.core namespace. Today, I am going to share with you some interesting usages of juxt, some and reduced.

Select several values from a map - with juxt

We have select-keys to create a submap of a map.

(select-keys {:a 1 :b 2 :c 3} [:a :b])

But what if we want to get only the values?

We could chain select-keys and vals:

(-> (select-keys {:a 1 :b 2 :c 3} [:a :b])
    vals)

But it doesn’t feel idiomatic.

It’s much cleaner to use juxt:

((juxt :a :b) {:a 1 :b 2 :c 3})

Find an item in a sequence - with some

We can find an item in a sequence with (first (filter ...)):

(first (filter #(= % :c) [:a :b :c :d]))

But it’s much more idiomatic to use some and a set as a predicate:

(some #{:c} [:a :b :c :d])

It works fine because in clojure, a set behaves as a function that receives an argument and returns it if it belongs to the set - and nil otherwise:

(#{:c} :c)
(#{:c} :a)

Terminates a reduce - with reduced

How do you terminate a reduce once you have found the value that you were looking for?

For instance, let’s imagine that you want to sum a sequence of positive numbers with a tweak: if the sum is greater than 1000 you want to return :big-sum instead of the sum.

You could write it with reduce:

(defn my-sum [s]
  (let [res (reduce (fn [sum x]
                      (+ sum x))
                    0
                    s)]
    (if (>= res 1000)
      :big-sum
      res)))

(my-sum (range 100))

But - inside the reduce - once you have discovered that the sum is greater than 1000, there is no point of continuing the calculation (because all the numbers are positive).

Let’s terminate our reduce with reduced:

(defn my-sum-opt [s]
  (reduce (fn [sum x]
            (let [res (+ sum x)]
              (if (>= res 1000)
                (reduced :big-sum)
                res)))
            0
            s))

(my-sum-opt (range 100))