2013-07-06 5 views
6

Ich habe in mehreren Situationen ausgeführt, in denen ich eine Kette von Operationen auf einem Objekt mit optionalen Funktionen ausführen möchte. "->" eignet sich hervorragend für Sequenzen von Befehlen auf demselben Objekt (zB (c (b (a x))) wird (-> x a b c)), außer wenn einige Operationen optional sind. Angenommen, ich tun wollte: clojure's -> (Pfeil) Operator und optionale Operationen

(c 
    (if (> (a x) 2) 
    (b (a x)) 
    (a x) 
    ) 
) 

Gibt es eine Möglichkeit zu tun, dass in einer klareren Weise unter Verwendung einer Operation wie „->“?

Antwort

10

Sie können es mit cond-> führte neu in Clojure 1,5:

(cond-> x 
    true  a 
    (> (a x) 2) b 
    true  c) 

Oder besser,

(-> x 
    a 
    (cond-> (> (a x) 2) b) 
    c) 

Bedeutung, „nehmen x, fädeln Sie es durch a, nehmen Sie das Ergebnis und thread es durch b wenn (> (a x) 2) oder sonst lassen Sie es unverändert, schließlich nehmen Sie, was Sie haben und fädeln Sie es durch c ".

Mit anderen Worten, ist cond-> wie ->, außer statt einzelner Formen Ihren Ausdruck einzufädeln durchPaare Test + Form annimmt, wobei die Form wird übersprungen, wenn der Test zum Einfädeln Falsey und verwendet wird, wenn der Test ist truthy:

(cond-> x 
    test-1 form-1 
    test-2 form-2) 

;; if test-1 is truthy and test-2 is falsey, output is as if from 
(-> x test-1) 

;; if it's the other way around, output is as if from 
(-> x test-2) 

;; if both tests are truthy: 
(-> x test-1 test-2) 

;; if both tests are falsey: 
x 
+3

Übrigens ist 'cond->' mein persönlicher Champion im unverständlichsten Docstring-Wettbewerb. –

+1

Eine andere Umformulierung: "Nimmt x und Klauseln, interpretiert Klauseln als Paare von Test und Ausdruck, dann threads x durch jene Ausdrücke, für die die entsprechenden Tests truthy sind." –

+0

Pallets [thread-expr] (https://github.com/pallet/thread-expr) hat mehr, ähnliche fns. – noahlz