Clojure:为什么Ref失去了Assoc

时间:2013-04-14 04:43:46

标签: clojure ref stm

我正在Clojure中更新地图参考中的计数器。

(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 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
#<Ref@65dcc2a3: {yellow #<Ref@3e0d1329: 1>}>  
#<Ref@65dcc2a3: {yellow 2}>

在这种情况下,如何在更新时保留相同的引用?

1 个答案:

答案 0 :(得分:3)

你快到了。下面是解决方案,检查increment-key的最后一行,你只需要改变值(不要改变你正在做的地图中的键,因为这导致使用alter return value更新键在你的例子中是2,记得alter返回ref的新值,而不是ref本身)。也不要在def中使用def,你应该使用let(在你的-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)))