2015-07-31 10 views
11

In Haskell, wir Data.Function.on haben:Gibt es in Clojure eine Funktion wie Haskell?

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

In Clojure, ich möchte in der Lage sein zu definieren, beispielsweise ein Anagramm Prädikat wie folgt:

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

Es ist trivial zu implementieren:

Aber gibt es eine eingebaute Funktion , die die s bewerkstelligt ein Ziel? Ich kann nicht einen finden.

+4

vielleicht '(defn auf [gf] # (gilt g (map f% &)))' in clojures varargs-wenn-möglich Geist – noisesmith

Antwort

4

Nein, es gibt keine eingebaute Funktion, die das tut, wonach Sie suchen. Wenn Sie es umsetzen werden, aber ich glaube, können Sie es sich leisten, ein wenig mehr generisch zu sein, da Clojure Vararg Unterstützung hat und es fehlt currying:

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

Auf diese Weise können Sie so etwas wie

(defn same-parity? [x y] 
    ((on = mod 2) x y)) 
schreiben

natürlich, die in Haskell zu einfach ist, wie

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

Aber in Clojure die partielle Anwendung von mod ein wenig schwieriger ist, so dass es übergleichwertige Funktionalität bereitzustellen üblich istargs wenn du kannst.

+0

Die Varargs-Version von 'on' reibt mich in die falsche Richtung ... Bin ich richtig gelesen, dass '((on = mod 2) xy)' äquivalent zu '(= (mod x 2) (mod y 2))'? Ich mag die Haskell-Version gut, da ('mod' 2) explizit über die Reihenfolge der Argumente ist, aber in Clojure hätte ich' (mod 2 x) 'nicht' (mod x 2) 'erwartet. – yurrriq

+1

@EricBailey Hat eine alte Version mit einem '(fn [x y])' eingefügt, tut mir leid. Was die Varargs-Reihenfolge angeht, ist meins definitiv die Reihenfolge, die zu anderen partiell anwendenden Funktionen passt. Vergleichen Sie zB '(swap! X/10)': das ist umgewandelt in '(swap! X # (/% 10))', nicht '(swap! X # (/ 10%))'. Es mag unnatürlich aussehen, wenn Sie an Haskell gewöhnt sind, aber diese Reihenfolge ist viel nützlicher als die Alternative. – amalloy

+0

Bei zweiter Überlegung macht '(mod x 2)' in Clojure mehr Sinn, ich habe einfach keine Lust auf die Varargs-Version. – yurrriq