2013-08-14 24 views
6

tôi muốn làm điều này:Tại sao vị trí đối số của phân tách và tham gia trong clojure.string bị lẫn lộn?

(-> string 
    (str/split "\s") 
    (modification-1) 
    (modification-2) 
    … 
    (modification-n 
    (str/join "\n")) 

Nhưng không, chia mất [s regex] và tham gia diễn [seperator coll].

Có lý do rõ ràng nào cho sự điên rồ này không (đọc: Quyết định thiết kế đằng sau điều này) là gì?

+1

Điều gì là sai với? (tham gia "\ n" (chuỗi phân tách "\ s")) – Chiron

+0

Tôi đã bỏ qua một vài chức năng sửa đổi ở giữa. Thêm chúng để làm rõ. – Profpatsch

+0

Tại sao? 'clojure.string.join' phù hợp với các hàm khác có bộ sưu tập. '(map f col) (bộ lọc f col)' –

Trả lời

8

Kể từ Clojure 1.5, bạn cũng có thể sử dụng một trong các luồng luồng mới.

clojure.core/như->

([expr tên & hình thức])

Macro tên

liên kết với expr, đánh giá các hình thức đầu tiên trong bối cảnh từ vựng đó ràng buộc, sau đó liên kết tên với kết quả đó, lặp lại cho mỗi hình thức liên tiếp , trả về kết quả của biểu mẫu cuối cùng.

Đó là khá một cấu trúc mới, vì vậy không chắc chắn làm thế nào để sử dụng idiomatically nêu ra, nhưng tôi đoán một cái gì đó như thế này sẽ làm:

(as-> "test test test" s 
    (str/split s #" ") 
    (modification-1 s) 
    (modification-2 s) 
    ... 
    (modification-n s) 
    (str/join "\n" s)) 

Sửa

Đối với lý do tại sao vị trí lý luận khác nhau, tôi không có chỗ để nói, nhưng tôi nghĩ rằng đề nghị của Arthur có ý nghĩa:

  • Một số chức năng hoạt động rõ ràng trên các bộ sưu tập (map, reduce, v.v ...). Chúng có xu hướng luôn lấy bộ sưu tập làm đối số cuối cùng, có nghĩa là chúng hoạt động tốt với ->>
  • Một số chức năng không hoạt động trên bộ sưu tập và có xu hướng lấy đối số quan trọng nhất (là một điều?) tranh luận. Ví dụ: khi sử dụng /, chúng tôi dự kiến ​​tử số sẽ đến trước. Các chức năng này hoạt động tốt nhất với ->

Vấn đề là - một số chức năng không rõ ràng. Họ có thể lấy một bộ sưu tập và tạo ra một giá trị duy nhất, hoặc lấy một giá trị duy nhất và tạo ra một bộ sưu tập. string\split là một ví dụ (bỏ qua khoảnh khắc thêm nhầm lẫn rằng một chuỗi có thể được coi là cả một giá trị đơn hoặc một bộ sưu tập).Ghép/giảm hoạt động cũng sẽ làm điều đó - họ sẽ mess up đường ống của bạn!

Xem xét, ví dụ:

(->> (range 1 5) 
    (map inc) 
    (reduce +) 
    ;; at this point we have a single value and might want to... 
    (- 4) 
    (/ 2)) 
    ;; but we're threading in the last position 
    ;; and unless we're very careful, we'll misread this arithmetic 

Trong những trường hợp này, tôi nghĩ rằng một cái gì đó giống như as-> là thực sự hữu ích.

Tôi nghĩ chung hướng dẫn sử dụng ->> khi hoạt động trên bộ sưu tập và -> nếu không là âm thanh - và chỉ trong những trường hợp biên giới/không rõ ràng này, as-> có thể làm cho mã trở nên rõ ràng hơn một chút.

+2

Yêu thích macro mới này. Có một thư viện có thể làm được điều này, tuyệt vời khi thấy nó đến trong 'lõi'. – Profpatsch

+3

Điều này tốt hơn nhiều so với cách cũ và làm cho mã dễ đọc hơn nhiều vì tôi không phải tưởng tượng đối số còn thiếu khi tôi đọc nó. –

+0

Thực hiện một ngọn đuốc cho [tag: ra], tôi thích macro luồng, nhưng đã bí mật hy vọng cho một luồng tương đương 'swap',' roll' và 'dup' để thao tác thứ tự đối số. Ah tốt. –

2

Bạn có thể sử dụng chức năng một phần để sửa đối số dấu phân tách cho str/join.

(-> string 
    (str/split #"\s") 
    (modification-1) 
    (modification-2) 
    ;; 
    (modification-n) 
    ((partial str/join "\n"))) 
+0

tôi cho rằng sẽ đặt chuỗi thành dạng một phần. bao quanh nó với dấu ngoặc vuông? –

+0

bạn cũng có thể làm ... (sửa đổi-n) (- >> (str/join "\ n"))) –

+0

Bạn có chắc nó sẽ hoạt động không? Dường như với tôi rằng kết quả của sửa đổi-n sẽ được luồng trước khi str/join trong một phần. – Blacksad

2

Tôi cũng chạy vào loại nhức đầu luồng nhỏ này khá thường xuyên.

(-> string 
    (str/split "\s") 
    (modification-1) 
    (modification-2) 
    … 
    (modification-n 
    (#(str/join "\n" %))) 

và thường tạo chức năng ẩn danh để thực hiện khớp thứ tự. Tôi đoán là tại sao một số chức năng được sử dụng với thread đầu tiên ->, một số cho thread cuối cùng ->> và đối với một số luồng không phải là một mục tiêu thiết kế, mặc dù đây chỉ là một đoán.

+0

Chấp nhận điều này vì nó hoạt động cho mọi chức năng và cố gắng tìm câu trả lời cho câu hỏi. – Profpatsch

+0

Tôi đoán mũi tên thứ hai phải là '- >>'. – Profpatsch

+0

cố định :-) * đỏ mặt * –

0

Không có gì sai với luồng biểu ren của bạn thông qua một vĩ mô luồng, như thế này là:

(-> string 
    (str/split "\s") 
    modification-1 
    modification-2 
    modification-n 
    (->> (str/join "\n")))