在Clojure中,有没有像Haskell这样的函数?

In Clojure, is there a function like Haskell's on?

在 Haskell 中,我们有 Data.Function.on:

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(.*.) `on` f = \x y -> f x .*. f y

在 Clojure 中,我希望能够定义,例如, 一个字谜谓词如下:

(defn anagram? [word other-word]
  (and (not= word other-word)
       ((on = sort) word other-word)))

实现起来很简单:

(defn on [g f] (fn [x y] (g (f x) (f y))))

但是有没有内置函数 实现相同的目标? 我好像找不到。

不,没有内置功能可以满足您的需求。不过,如果您要实现它,我认为您可以负担得起更通用的代码,因为 Clojure 支持可变参数并且缺少柯里化:

(defn on
  ([f g]
     (fn [x y]
       (f (g x)
          (g y))))
  ([f g & args]
     (on f #(apply g % args))))

这样你就可以写出类似

的内容
(defn same-parity? [x y]
  ((on = mod 2) x y))

这当然在 Haskell 中也很容易,因为

sameParity :: (Integral a) => a -> a -> Bool
sameParity = (==) `on` (`mod` 2)

但是在 Clojure 中 mod 的部分应用有点棘手,所以如果可以的话,习惯上通过 &args 提供等效的功能。