2013-04-14 2 views
0

Я работаю над обновлением счетчиков на карте ref в Clojure.Clojure: Почему Ref Lost on Assoc

(defn increment-key [this key] 
    (dosync 
     (let [value (get @this key)] 
      (if (= value nil) 
       (alter this assoc key (ref 1)) 
       (alter this assoc key (alter value inc)))))) 

Однако, это выглядит как заявление альтер значение ИНК теряет ссылку:

(defn -main [& args] 
    (def my-map (ref {})) 
    (increment-key my-map "yellow") 
    (println my-map) 
    (increment-key my-map "yellow") 
    (println my-map)) 

который печатает:

$ lein run 
#<[email protected]: {yellow #<[email protected]: 1>}> 
#<[email protected]: {yellow 2}> 

Как я могу сохранить ту же ссылку, обновляя его в этот сценарий?

+0

Hate быть, что парень, но можно показать до и после того, что именно вы пытаетесь делать? Вы говорите «ключ обновления», но вывод выглядит так, как будто он увеличивает значение. Возможно, в последнее время я смотрел слишком много javascript, но «этот» атом немного меня пугает. – dizzystar

+0

Несомненно. На самом деле до и после есть функция '-main' выше. Я начинаю с пустого ref, а затем увеличиваю значение, связанное с ключом «желтый» с помощью клавиши «increment-key». 'this', в данном случае, не является специальной формой,' this' были вызваны 'my-object-ref'. –

+0

Я начал немного просматривать и заметил, что у вас есть еще 2 темы по этому вопросу. Что здесь отличает, что вы пытаетесь решить, что эти потоки не говорят вам и почему вы не используете те же идеи, что и вам? Я думаю, что вы неверно истолковываете то, что означает «состояние» и «неизменность», и вы можете прочитать об этом. Прочитайте всю эту главу, и вы будете просветлены: http://mitpress.mit.edu/sicp/full-text/book/book-ZH-19.html#%_chap_3 – dizzystar

ответ

2

Вы были почти там. Ниже приведено решение, проверьте последнюю строку increment-key, вам просто нужно изменить значение (не изменяя ключ на карте, как вы делали, coz, вызывающий обновление ключа с возвращаемым значением alter, которое в вашем примере было 2, помните, что alter возвращает новое значение ref, а не ref). Также не используйте Защиту внутри опр, вы должны использовать позволить (в вашей -main функции)

(defn increment-key [this key] 
    (dosync 
     (let [value (get @this key)] 
      (if (= value nil) 
       (alter this assoc key (ref 1)) 
       (alter value inc))))) 

(defn -main [& args] 
    (let [my-map (ref {})] 
     (increment-key my-map "yellow") 
     (println my-map) 
     (increment-key my-map "yellow") 
     (println my-map))) 
+0

Thats красивый мужчина, спасибо, делает 100% смысл. –