Predicate testing for equality that returns the common element

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
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)))
clojure
add a comment |Â
up vote
1
down vote
favorite
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)))
clojure
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
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)))
clojure
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)))
clojure
edited Feb 9 at 22:46
asked Feb 9 at 21:49
Carcigenicate
2,32411128
2,32411128
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
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.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
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.
add a comment |Â
up vote
1
down vote
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.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
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.
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.
edited Feb 9 at 23:18
answered Feb 9 at 23:12
Carcigenicate
2,32411128
2,32411128
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187221%2fpredicate-testing-for-equality-that-returns-the-common-element%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password