2013-04-14 55 views
0

我正在更新Clojure中的地图ref中的计数器。Clojure:为什么Ref在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)))))) 

但是,它看起来像ALTER值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

讨厌自己是那样的人,但可能是之前表现出与它是什么,你正试图后做?你说“更新密钥”,但输出看起来像是递增值。也许我最近一直在盯着太多的javascript,但“这个”原子让我感到有些害怕。 – dizzystar

+0

当然可以。其实前后都在'-main'函数中。我从一个空引用开始,然后用'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的最后一行,你只需要改变这个值(不要像你在做的那样改变地图中的键,因为这会导致键被更新为更新返回值,在你的例子中是2,记住alter会返回ref的新值,而不是ref本身)。也不要在里面高清高清使用,你应该使用让(在你的 - 主要功能)

(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

这就是美丽的男人,谢谢,使100%的感觉。 –