In Haskell, we have Data.Function.on
:
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(.*.) `on` f = \x y -> f x .*. f y
In Clojure, I want to be able to define, for example, an anagram predicate as follows:
(defn anagram? [word other-word]
(and (not= word other-word)
((on = sort) word other-word)))
It's trivial to implement:
(defn on [g f] (fn [x y] (g (f x) (f y))))
But is there any built-in function that accomplishes the same goal? I can't seem to find one.
No, there is no built-in that does what you are looking for. If you are going to implement it, though, I think you can afford to be a little more generic, since Clojure has vararg support and lacks currying:
(defn on
([f g]
(fn [x y]
(f (g x)
(g y))))
([f g & args]
(on f #(apply g % args))))
This lets you write something like
(defn same-parity? [x y]
((on = mod 2) x y))
which of course is easy in Haskell too, as
sameParity :: (Integral a) => a -> a -> Bool
sameParity = (==) `on` (`mod` 2)
But in Clojure the partial application of mod is a little trickier, so it's customary to provide equivalent functionality via &args if you can.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With