loop

La récursivité en Clojure pose le même problème qu'en Java ou en JavaScript: la stack overflow.

loop permet de réaliser de manière sûre ce genre de récursion. Tout d'abord, loop ressemble à let car la même syntaxe est utilisée pour définir une ou des valeurs initiales.

Ensuite, loop prendra une form. Cette form contiendra généralement une condition d'arrêt, et le mot clé recur.

recur fera revenir l'exécution au début de loop, sauf que les valeurs par des variables déclarés vaudront maintenant les paramètres passés à recur et non les valeurs initiales.

La condition d'arrêt est là pour arrêter l'exécution et retourner un résultat.

Exemple détaillé

Prenons par exemple le code suivant:

(loop [counter 5
       result []]
  (if (= counter 0)
    (println result n)
    (recur (dec counter)
           (conj result counter))))

L'exécution peut être visualisée comme suit:

  • Au début, les variables counter et result valent respectivement 5 et [].

  • counter n'est pas égal à 0, recur est donc appelé avec les résultats de (dec counter) et (conj result counter), c'est à dire (recur 4 [5]).
  • recur ayant été appelé, nous revenons au début de loop sauf que maintenant counter vaudra 4 et result vaudra [5].
  • counter n'est toujours pas égal à 0, recur est donc rappelé avec les nouveaux résultats de (dec counter) et (conj result counter), c'est à dire (recur 3 [5 4]).
  • L'itération se répète jusqu'à ce que counter soit à 0. A ce moment là, recur n'est pas appelé, on appelle println et l'on sort de la loop.

loop est une construction intéressante, mais en Clojure son utilisation est très limitée. Il est plus intéressant d'utiliser des fonctions comme map, reduce ou filter que nous verrons dans la suite de ce tutoriel.

Précédent - Suivant -

(loop [counter 5
       result []]
  (if (= counter 0)
    (println result "\n")
    (recur (dec counter)
           (conj result counter))))

(loop [my-vector (range 10)
       result 0]
  (if my-vector
    (recur (next my-vector)
           (+ result (first my-vector)))
    (println result "\n")))

powered by mcorbin - Available on Github