Atomes
Les atomes permettent de gérer un état partagé, synchrone et indépendant. Ce sont des types référence, comme les références (refs) et les variables (vars). On crée un atome avec `atom` et on accède à son état avec `deref` ou `@`. À l'instar des références et des agents, les atomes prennent en charge les validateurs. Pour modifier la valeur d'un atome, on utilise `swap!`. Une fonction de comparaison et d'affectation (compare-and-set!) de plus bas niveau est également disponible. Les modifications apportées aux atomes sont toujours exemptes de conditions de concurrence.
Comme pour tous les types référence, l'utilisation prévue d'un atome est de contenir une structure de données immuable de Clojure. Et, de manière similaire à `alter` pour les références et à `send` pour les agents, on modifie la valeur en appliquant une fonction à l'ancienne valeur. Ceci est réalisé de manière atomique par `swap!`. En interne, `swap!` lit la valeur actuelle, lui applique la fonction et tente de l'affecter par comparaison et affectation (compare-and-set!). Comme un autre processus léger peut avoir modifié la valeur entre-temps, il peut être nécessaire de réessayer, ce qui se fait dans une boucle d'attente active (swap-loop). En résumé, la valeur sera toujours le résultat de l'application atomique de la fonction fournie à la valeur actuelle. Cependant, comme la fonction peut être appelée plusieurs fois, elle doit être sans effets de bord.
Les atomes constituent un moyen efficace de représenter un état qui n'aura jamais besoin d'être coordonné avec un autre et pour lequel vous souhaitez effectuer des modifications synchrones (contrairement aux agents, qui sont également indépendants mais asynchrones). Un exemple d'utilisation typique est la mémoïsation.
- (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"
Fonctions associées
| Catégorie | Fonctions |
|---|---|
| Créer un atome | atom |
| Examiner un atome | deref (see also the @ reader macro) |
| Modifier l'état de l'atome | swap! reset! swap-vals! reset-vals! |
| Validateurs | set-validator! get-validator |
| Observateurs | add-watch remove-watch |