2013-03-08 7 views
11

Wie ich verstehe, gehen und Karte beide eine Funktion auf eine Seq anwenden. (Walk erlaubt auch die Anwendung einer outer Funktion Post Processing). Was sind jedoch die idiomatischen Fälle der Verwendung eines über dem anderen?Spaziergang vs Karte für die Verarbeitung einer Seq

+1

eine Funktion auf einen seq Anwendung der Job von 'map' ist. Verwenden Sie 'walk', wenn Sie sowohl durch als auch rekursiv in die gesamte Struktur gehen müssen. –

+0

@ A.Webb können Sie es als Antwort posten. Ich möchte es als die Antwort markieren. Ich freue mich auch, wenn Sie auf einige Beispiele von Spaziergang hinweisen können. – murtaza52

+1

Beantwortet meine Frage nicht? – sethev

Antwort

6

Anwenden einer Funktion auf eine Seq ist die Aufgabe der Karte. Verwenden Sie walk, wenn Sie sowohl durch als auch rekursiv in die gesamte Struktur gehen müssen.

Einige Beispiele von walk können gefunden werden bei ClojureDocs, ebenfalls erhältlich bei der REPL, z. (user/clojuredocs clojure.walk/postwalk). Viele der Beispiele sind pädagogisch und könnten und sollten mit map oder for (und manchmal reduce) in der Praxis gemacht werden.

Der typische Anwendungsfall für eine walk ist, wenn Sie eine verschachtelte Struktur haben, die Sie rekursiv verarbeiten möchten. Einige Beispiele, wo dies nützlich sein könnte, sind der clojure.walk Namensraum selbst, z. schau dir (source clojure.walk/keywordize-keys) an.

Ein weiteres Beispiel, das den Sinn kommt, ist die Interpretation Parse-Bäume [. Verwendung Reißverschlüsse (oder tree-seq für einige einfachere iterative Fälle) Hinweis, wenn Sie es iterativ oder nach Belieben, bearbeiten wollen]:

(require '[clojure.walk :as w]) 

(def t [+ [* [- 6 2] [/ 9 3]] [* 2 [+ 7 8]]]) 

(w/postwalk #(if (and (coll? %) (fn? (first %))) (apply (first %) (next %)) %) t) 
;=> 42 

Vielleicht nützlich, wenn zB mit einem allowed-fn?fn? ersetzen usw. ein Ausdruck auszuwerten, anstatt das zu mächtig eval Compiler von Aufrufen:

(eval t) ;=> [#<core$_PLUS_ ... ] 

Oops, Formulare Listen, nicht VEC toren:

(def s (w/postwalk #(if (coll? %) (apply list %) %) t)) 
s ;=> (#<core$_PLUS_ ...) 
(eval s) ;=> 42 

Ah, bemerken hier eine andere Verwendung eines walk - die Struktur von verschachtelten Vektoren zu verschachtelten Listen rekursiv ändern.

Ein iteratives Beispiel zu meditieren:

(require '[clojure.walk :as w]) 

(def s1 (range 8)) 
s1 ;=> (0 1 2 3 4 5 6 7) 
(map inc s1) 
;=> (1 2 3 4 5 6 7 8) 
(w/postwalk #(if (number? %) (inc %) %) s1) 
;=> (1 2 3 4 5 6 7 8) 

(def s2 (partition 2 s1)) 
s2 ;=> ((0 1) (2 3) (4 5) (6 7)) 
(map (partial map inc) s2) 
;=> ((1 2) (3 4) (5 6) (7 8)) 
(w/postwalk #(if (number? %) (inc %) %) s2) 
;=> ((1 2) (3 4) (5 6) (7 8)) 

(def s3 (partition 2 s2)) 
s3 ;=> ((0 1) (2 3) (4 5) (6 7)) 
(map (partial map (partial map inc)) s3) 
;=> (((1 2) (3 4)) ((5 6) (7 8))) 
(w/postwalk #(if (number? %) (inc %) %) s3) 
;=> (((1 2) (3 4)) ((5 6) (7 8))) 

(def s4 (partition 2 s3)) 
s4 ;=> ((((0 1) (2 3)) ((4 5) (6 7)))) 
(map (partial map (partial map (partial map inc))) s4) 
;=> ((((1 2) (3 4)) ((5 6) (7 8)))) 
(w/postwalk #(if (number? %) (inc %) %) s4) 
;=> ((((1 2) (3 4)) ((5 6) (7 8)))) 
10

Die Semantik für map ist im Grunde: die Funktion zu jedem Artikel in der Sammlung anzuwenden und die Ergebnisse lazily in einer Sequenz zurück:

(map inC#{0 1 2}) ;outputs (when realized) (1 2 3) 

anzumerken, dass die Eingabe ein Satz war, aber der Ausgang ist eine Sequenz.

Die Semantik für zu Fuß sind im Grunde: eine Sammlung der gleichen Art machen, wobei jedes Element für das Element durch den Wert der inner Funktion ersetzt wurde, gibt das Ergebnis von outer auf die neue Kollektion Anwendung:

(walk inc identity #{0 1 2}) ;outputs #{1 2 3} 

Wenn Sie den Quellcode für die anderen Funktionen in der Walk-API (http://richhickey.github.com/clojure/clojure.walk-api.html) betrachten, können Sie sehen, wie die Wanderungen auch rekursiv machen (oder nur diese anderen Funktionen verwenden).

Soweit Idiome gehen, bin ich mir nicht sicher. Aber walk ist komplexer, so dass Sie wahrscheinlich map in Fällen bleiben sollten, in denen Sie nicht die Semantik benötigen, die walk bietet.

+0

Ich denke, die andere Antwort verdeutlicht den Unterschied besser. Jedoch +1 für deine Mühe und schätze es! – murtaza52