2012-08-17 57 views
6

Với các tình huống sau:Làm thế nào để cập nhật các bản ghi trong bản đồ ref trong Clojure?

(defrecord Person [firstname lastname]) 
(def some-map (ref {})) 

(dosync 
    (alter some-map conj {1 (Person. "john" "doe")}) 
    (alter some-map conj {2 (Person. "jane" "jameson")})) 

Để thay đổi firstname của "joe" thành "nick", tôi thực hiện như sau:

(dosync 
    (alter some-map (fn [m]     
        (assoc m 1 
         (assoc (m 1) :firstname "nick"))))) 

cách thành ngữ để làm điều này trong Clojure là gì?

Trả lời

5

Không cần phải sử dụng bản cập nhật, trong trường hợp này, việc xác nhận là chính xác những gì bạn muốn.

(dosync (alter some-map assoc-in [1 :firstname] "nick"))

+0

Đồng ý, cập nhật trong quá chung chung trong trường hợp này. –

2

Chỉnh sửa: Ví dụ: assoc-in của bạn tốt hơn, vì bạn bỏ qua giá trị trước đó. Giữ câu trả lời này đối với trường hợp bạn thực sự cần những giá trị theo thời gian:

Các update-in ở đó để cập nhật cấu trúc lồng nhau:

(alter some-map update-in [1 :firstname] (constantly "nick")) 

Đối số cuối cùng là một chức năng trên giá trị được "thay thế" (như assoc , nó không thay thế nhưng trả về một cấu trúc mới.) Trong trường hợp này, giá trị cũ bị bỏ qua, do đó hàm constantly luôn trả về "nick".

+0

bạn có thể bỏ qua chức năng bao bọc vô danh: '(thay đổi một số bản đồ cập nhật trong [1: firstname] (liên tục "nick"))' –

+0

@JoostDiepenmaat Cảm ơn, tôi cứ quên về tùy chọn đối số cho các hàm bậc cao hơn trong Clojure, sẽ chỉnh sửa. –

+0

Tôi chấp nhận câu trả lời khác, nhưng cảm ơn bạn đã đề xuất của bạn. Tôi không biết về liên tục; bây giờ tôi hiểu tại sao những nỗ lực khác của tôi thất bại. – Odinodin

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