2013-03-08 23 views
11

Khi tôi hiểu việc đi bộ và bản đồ cả hai áp dụng một hàm cho một seq. (đi bộ cũng cho phép ứng dụng xử lý bài đăng outer). Tuy nhiên, các trường hợp thành ngữ sử dụng cái nào khác hơn?walk so với bản đồ để xử lý một seq

+1

Áp dụng một chức năng để một seq là công việc của 'map'. Sử dụng 'walk' khi bạn phải đi qua cả hai và xuyên suốt vào toàn bộ cấu trúc. –

+0

@ A.Webb bạn có thể đăng nó làm câu trả lời hay không. Tôi muốn đánh dấu nó là câu trả lời. cũng sẽ đánh giá cao nếu bạn có thể chỉ ra một số ví dụ về đi bộ. – murtaza52

+1

Tôi không trả lời câu hỏi của bạn? – sethev

Trả lời

6

Áp dụng hàm cho seq là công việc của bản đồ. Sử dụng đi bộ khi bạn phải đi ngang qua và đệ quy vào toàn bộ cấu trúc.

Một số ví dụ về walk s có thể được tìm thấy tại ClojureDocs, cũng có sẵn tại REPL, ví dụ: (user/clojuredocs clojure.walk/postwalk). Nhiều người trong số các ví dụ là sư phạm và có thể và nên được thực hiện với map hoặc for (và đôi khi reduce) trong thực tế.

Trường hợp sử dụng điển hình cho walk là khi bạn có cấu trúc lồng nhau mà bạn muốn xử lý đệ quy. Một số ví dụ về điều này có thể hữu ích là chính không gian tên clojure.walk, ví dụ: xem (source clojure.walk/keywordize-keys). [. Lưu ý, nếu bạn muốn để xử lý nó lặp đi lặp lại hoặc theo ý muốn, sử dụng khóa kéo (hoặc tree-seq đối với một số trường hợp lặp đi lặp lại đơn giản hơn)]

Một ví dụ mà nói đến cái tâm được giải thích cây phân tích cú pháp:

(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 

lẽ hữu ích nếu, ví dụ, thay thế fn? với một allowed-fn?, vv để đánh giá một biểu thức , thay vì cách gọi trình biên dịch eval quá mạnh:

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

Rất tiếc, hình thức được liệt kê, không VEC TOR:

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

Ah, thông báo ở đây khác sử dụng một walk - đệ quy thay đổi cấu trúc từ vectơ lồng vào danh sách lồng nhau.

Một ví dụ lặp đi lặp lại để suy gẫm:

(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

Ngữ nghĩa cho map cơ bản: áp dụng các chức năng cho từng hạng mục trong bộ sưu tập và trả lại kết quả một cách lười biếng trong một chuỗi:

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

Lưu ý rằng các đầu vào là một bộ nhưng sản lượng là một chuỗi.

Ngữ nghĩa cho đi bộ về cơ bản: thực hiện một bộ sưu tập cùng loại nơi từng hạng mục đã được thay thế bởi giá trị của inner chức năng cho mục đó, trả lại kết quả của việc áp dụng outer để bộ sưu tập mới:

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

Nếu bạn nhìn vào mã nguồn cho các chức năng khác trong API đi bộ (http://richhickey.github.com/clojure/clojure.walk-api.html), bạn có thể xem cách làm cho các đường đi bộ cũng đệ quy (hoặc chỉ sử dụng các chức năng khác).

Theo như thành ngữ đi, tôi không chắc chắn. Nhưng walk phức tạp hơn, do đó bạn có thể phải gắn bó với map trong trường hợp bạn không cần ngữ nghĩa mà walk phiếu mua hàng.

+0

Tôi nghĩ câu trả lời khác minh họa tốt hơn sự khác biệt. Tuy nhiên 1 cho nỗ lực của bạn và đánh giá cao nó! – murtaza52

Các vấn đề liên quan