2016-12-21 11 views
2

{:a 1}のような単純なアトムを更新したいと思います。与えられたキーが既に存在する場合にのみswap!のように新しい値を返します。そうでなければnilを返します。原子と条件付きのマップ更新

これは、私は考え出した最も簡単な解決策です:

(defn cond-assoc [store k v] 
    (when (get @store k) 
    (swap! store assoc k v))) 

が、私はそれが本当にアトミックだ感じることはありません。野生のものでは、(get @store k)swap!の間で何かが起こることがあります。そこより良い解決策はありますか?

答えて

5

あなたが正しいです、あなたのソリューションはあまり原子的ではありません。これは、原子または原子であることとは何の関係もないことを

(defn assoc-if-exists [m k v] 
    (if (m k) (assoc m k v) m)) 

注:アトミックスワップを行うために、必要な場合にのみマップを変換単純な関数を作ります。原子と一緒に使用するには、単に

(def store (atom {:a 1})) 
(swap! store assoc-if-exists :a 4) ;; {:a 4}, value changed 
(swap! store assoc-if-exists :b 4) ;; {:a 4}, nothing added 

キーが存在しないときにはnilを返さないことに注意してください。その動作が必要な場合は、戻り値にキーが含まれているかどうかを確認できます。

(defn atomic-assoc-or-nil [a k v] 
    (let [r (swap! a assoc-if-exists k v)] 
    (when (get r k) r)))