Predicate testing for equality that returns the common element I'm going to try brute-forcing the solving of a Magic Square. To simplify the code later on, I wanted a function similar to =, but one that returns the common element if all the elements are equal and nil otherwise. This is unlike = which always returns either true or false. I'm calling it =? for lack of a better name.

Example:

(=? 1 2 1)
nil ; nil because they're not all the same

(=? 1 1 1)
1 ; Returns the common element of 1


Obviously, this function won't work well when nil may be the sole element in a collection, since it will return falsey even if all the elements are the same, but nil.

I thought that there must be some kind of core operation I could use here, but after a few minutes of thinking, I couldn't think of any. I ended up rolling my own function using loop. I'd like general advice on the function that I wrote, or potentially a more idiomatic way to write it that I'm missing. It looks exceedingly clunky to me; especially after I realized the need for the last-arg accumulator. A recursive solution would be nice, as I fear I'm missing something obvious here:

(defn =?
  "Checks if every supplied argument =s every other.
  Returns the common element if they're all the same, nil otherwise."
  [&amp; args]
  (loop [[f-arg &amp; r-args] (rest args)
         last-arg (first args)]
    (cond
      (nil? f-arg) last-arg
      (= f-arg last-arg) (recur r-args f-arg)
      :else nil)))
Soon after I posted this, I went for a walk and realized that this is the perfect opportunity to use reduce. I'm kind of embarrassed that I didn't see it originally, but this was my train of thought that lead me to what I'm much happier with.

First, I tried a simple reduction. This was pretty simple, although still a little verbose:

(defn =?2 [&amp; args]
  (reduce (fn [acc n]
              (if (= n acc)
                n
                (reduced nil)))
          (first args)
          (rest args)))


I decided that this was probably simple enough to use a function macro for. Normally I don't like using them for reductions, but there's not much going on here:

(defn =?3 [&amp; args]
  (reduce #(if (= % %2) % (reduced nil))
          (first args)
          (rest args)))


I don't like using explicit calls to first and rest, as I find they're usually neater when they're implicit in a deconstruction. I decided to deconstruct the arguments instead:

(defn =?4 [&amp; [arg &amp; rest-args]]
  (reduce #(if (= % %2) % (reduced nil))
          arg
          rest-args))


Then I checked what = uses, and found that it just uses multiple argument lists, so I tried that. This strikes me as the more idiomatic solution:

(defn =?5
  ([] nil)
  ([arg] arg)
  ([arg &amp; args]
   (reduce #(if (= % %2) % (reduced nil))
           arg
           args)))


I'm torn between 4 and 5, but I think that both are a significant improvement.