Section courante

A propos

Section administrative du site

Réducteurs

Les réducteurs offrent une approche alternative à l'utilisation des séquences pour manipuler les collections Clojure standard. Les fonctions de séquence sont généralement appliquées de manière paresseuse, séquentiellement, générant des résultats intermédiaires et dans un seul processus léger. Cependant, de nombreuses fonctions de séquence (comme `map` et `filter`) pourraient conceptuellement être appliquées en parallèle, ce qui permettrait d'obtenir un code plus rapide à mesure que le nombre de coeurs augmente. Pour plus de détails sur la logique des réducteurs, consultez les articles de blog originaux.

Un réducteur est la combinaison d'une collection réductible (une collection qui sait comment se réduire) et d'une fonction de réduction (la «recette» des opérations à effectuer lors de la réduction). Les opérations de séquence standard sont remplacées par de nouvelles versions qui ne réalisent pas l'opération, mais se contentent de transformer la fonction de réduction. L'exécution des opérations est différée jusqu'à la réduction finale. Ceci élimine les résultats intermédiaires et l'évaluation paresseuse caractéristiques des séquences.

De plus, certaines collections (vecteurs persistants et maps) sont pliables. L'opération de pliage sur un réducteur exécute la réduction en parallèle en procédant comme suit :

Si une collection ne prend pas en charge le pliage, elle utilisera à la place une réduction non parallèle.

Réduction et pliage

L'espace de noms clojure.core.reducers (aliasé ici r) fournit une fonction r/reduce alternative.

(r/reduce f coll)
(r/reduce f init coll)

La version avec réducteurs diffère en ce que :

En général, la plupart des utilisateurs n'appelleront pas directement `r/reduce` et privilégieront `r/fold`, implémentant une réduction et une combinaison parallèles. Cependant, il peut être utile d'effectuer une réduction immédiate avec moins de résultats intermédiaires.

(r/fold reducef coll)
(r/fold combinef reducef coll)
(r/fold n combinef reducef coll)

La fonction `r/fold` prend une collection réductible et la partitionne en groupes d'environ n éléments (512 par défaut). Chaque groupe est réduit à l'aide de la fonction `reducef`. Cette dernière est appelée sans argument afin de produire une valeur d'identité dans chaque partition. Les résultats de ces réductions sont ensuite réduits avec la fonction `combinef` (qui utilise `reducef` par défaut). Lorsqu'elle est appelée sans argument, `combinef` doit produire son élément d'identité ; cette opération sera effectuée plusieurs fois. Les opérations peuvent être exécutées en parallèle. L'ordre des résultats est préservé.

Les fonctions suivantes (analogues aux versions séquentielles) créent des réducteurs à partir d'une collection réductible ou pliable : `r/map`, `r/mapcat`, `r/filter`, `r/remove`, `r/flatten`, `r/take-while`, `r/take` et `r/drop`. Aucune de ces fonctions ne transforme la collection source. Pour obtenir un résultat cumulé, vous devez utiliser `r/reduce` ou `r/fold`. Pour produire une collection de sortie, utilisez clojure.core/into pour choisir le type de collection ou le r/foldcat fourni pour produire une collection réductible, pliable, séquentielle et comptée.

Utilisation des réducteurs

Utilisez la fonction `fold` pour effectuer une somme avec l'opérateur `+`.

  1. (require '[clojure.core.reducers :as r])
  2. (r/fold + (r/filter even? (r/map inc [1 1 1 2])))
  3. ;=> 6

Utiliser pour produire une collection finale :

  1. (into [] (r/filter even? (r/map inc (range 100000))))

Ou r/foldcat :

  1. (r/foldcat (r/filter even? (r/map inc (range 100000))))

Spécifiez une fonction de réduction et une fonction de combinaison avec fold :

  1. (defn count-words
  2.   ([] {})
  3.   ([freqs word]
  4.     (assoc freqs word (inc (get freqs word 0)))))
  5.  
  6. (defn merge-counts
  7.   ([] {})
  8.   ([& m] (apply merge-with + m)))
  9.  
  10. (defn word-frequency [text]
  11.   (r/fold merge-counts count-words (clojure.string/split text #"\s+")))

Quand utiliser

Utilisez la forme réductrice de ces opérations pour :

Utilisez la fonction `fold` lorsque :



Dernière mise à jour : Lundi, le 2 février 2026