# 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."
[& args]
(loop [[f-arg & 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)))


You don't need the single argument case. You can abbreviate to

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


However, the following is simpler still:

(defn =?
([] nil)
([x & xs]
(when (every? #(= x %) xs) x)))


We can even fold in the zero-argument case in by destructuring, as you do in =?4:

(defn =? [& [x & xs]]
(when (every? #(= x %) xs) x))


But this is too obscure for me.

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 [& 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 [& 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 [& [arg & 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 & args]
(reduce #(if (= % %2) % (reduced nil))
arg
args)))


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