Clojure

原子

原子提供一種管理共用、同步、獨立狀態的方式。它們是類似於參照和變數的參考類型。你可以使用 atom 建立原子,並可以使用 deref/@ 存取其狀態。與參照和代理一樣,原子支援驗證器。若要變更原子的值,你可以使用 swap!。同時也提供了較低層級的 compare-and-set!。對原子的變更永遠不會有競爭條件。

與所有參考類型一樣,atom 的預期用途是保存 Clojure 的不可變資料結構。而且,類似於 ref 的 alter 和 agent 的 send,您可以透過對舊值套用函數來變更值。這是透過 swap! 以原子方式完成的。在內部,swap! 會讀取目前值,對其套用函數,然後嘗試比較並設定!它。由於其他執行緒可能在中間時間變更值,因此它可能必須重試,並在旋轉迴圈中執行此動作。淨效應是,該值將永遠是供應函數套用至目前值後的結果,以原子方式。然而,由於函數可能被呼叫多次,因此它必須沒有副作用。

Atom 是表示某個狀態的有效方式,該狀態永遠不需要與任何其他狀態協調,而且您希望對其進行同步變更(與 agent 不同,後者類似地獨立但非同步)。典型的用法可能是用於記憶化

(defn memoize [f]
  (let [mem (atom {})]
    (fn [& args]
      (if-let [e (find @mem args)]
        (val e)
        (let [ret (apply f args)]
          (swap! mem assoc args ret)
          ret)))))

(defn fib [n]
  (if (<= n 1)
    n
    (+ (fib (dec n)) (fib (- n 2)))))

(time (fib 35))
user=> "Elapsed time: 941.445 msecs"

(def fib (memoize fib))

(time (fib 35))

user=> "Elapsed time: 0.044 msecs"

建立 Atom:atom

檢查 Atom:deref (另請參閱 @ reader 巨集)

變更 Atom 狀態:swap! reset! swap-vals! reset-vals!

觀察器:add-watch remove-watch