(defn do-to-map [amap keyseq f]
(reduce #(assoc %1 %2 (f (%1 %2))) amap keyseq))
Breakdown:
Nó giúp để nhìn vào nó trong ra ngoài. Trong Clojure, Hash-map hoạt động như các hàm; nếu bạn gọi chúng như một hàm với một khóa làm đối số, giá trị được kết hợp với khóa đó sẽ được trả về. Vì vậy, cho một chìa khóa duy nhất, giá trị hiện tại cho khóa đó có thể thu được thông qua:
(some-map some-key)
Chúng tôi muốn lấy giá trị cũ, và thay đổi chúng để các giá trị mới bằng cách gọi một số chức năng f
trên chúng. Vì vậy, với một khóa duy nhất, giá trị mới sẽ là:
(f (some-map some-key))
Chúng tôi muốn kết hợp giá trị mới này với khóa này trong bản đồ băm của chúng tôi, "thay thế" giá trị cũ. Đây là những gì assoc
làm:
(assoc some-map some-key (f (some-map some-key)))
("Thay thế" là trong sợ hãi dấu ngoặc kép bởi vì chúng ta không biến đổi một đối tượng băm-bản đồ duy nhất, chúng ta đang trở về mới, không thay đổi, thay đổi băm-map đối tượng mỗi lần chúng ta gọi là assoc
. Đây là vẫn nhanh và hiệu quả trong Clojure vì băm-bản đồ là dai dẳng và cơ cấu cổ phần khi bạn assoc
họ.)
chúng ta cần phải lặp đi lặp lại assoc
giá trị mới vào bản đồ của chúng tôi, một trong những chìa khóa cùng một lúc. Vì vậy, chúng tôi cần một số loại xây dựng looping. Những gì chúng tôi muốn là bắt đầu với bản đồ băm ban đầu của chúng tôi và một khóa duy nhất, sau đó "cập nhật" giá trị cho khóa đó. Sau đó, chúng tôi lấy bản đồ băm mới và khóa tiếp theo và "cập nhật" giá trị cho khóa tiếp theo đó. Và chúng tôi lặp lại điều này cho mỗi khóa, từng lần một và cuối cùng trả về bản đồ băm mà chúng tôi đã "tích luỹ". Đây là những gì reduce
làm.
- Đối số đầu tiên cho
reduce
là hàm lấy hai giá trị: giá trị "tích lũy", là giá trị chúng tôi giữ "cập nhật" lặp đi lặp lại; và một đối số được sử dụng trong một lần lặp để thực hiện một số tích lũy.
- Đối số thứ hai cho
reduce
là giá trị ban đầu được chuyển làm đối số đầu tiên cho số fn
này.
- Đối số thứ ba cho
reduce
là tập hợp các đối số được chuyển làm đối số thứ hai cho số này fn
, mỗi lần một đối số.
Vì vậy:
(reduce fn-to-update-values-in-our-map
initial-value-of-our-map
collection-of-keys)
fn-to-update-values-in-our-map
chỉ là assoc
tuyên bố từ trên cao, được bọc trong một chức năng ẩn danh:
(fn [map-so-far some-key] (assoc map-so-far some-key (f (map-so-far some-key))))
Vì vậy, cắm nó vào reduce
:
(reduce (fn [map-so-far some-key] (assoc map-so-far some-key (f (map-so-far some-key))))
amap
keyseq)
Trong Clojure, có một cách viết tắt để viết chức năng ẩn danh: #(...)
là một ẩn danh fn
bao gồm một biểu mẫu duy nhất, trong đó %1
được ràng buộc với đối số đầu tiên cho hàm ẩn danh, %2
đến thứ hai, v.v. Vì vậy, chúng tôi fn
từ trên có thể được viết tương đương như:
#(assoc %1 %2 (f (%1 %2)))
này cho chúng ta:
(reduce #(assoc %1 %2 (f (%1 %2))) amap keyseq)
Bạn có thể đưa ra tuyên bố bằng mô tả tuyên bố cho chúng tôi về Clojure mới không? –
Hy vọng rằng sẽ giúp. –
Ký hiệu # (...) này thật tuyệt vời. Câu trả lời chính xác! –