Comment implémenter une boucle For dans Clojure

J'aimerais implémenter ce petit code dans Clojure, mais je me bats:

struct mystruct {
   int id;
   int price;
};

mystruct mydata[10];

for (int i=0; i<10; i++) {
  myfunction(mydata[i].id, mydata[i].price);
  //other things...
}

Je suis un débutant avec Clojure et c'est vraiment compliqué pour moi de faire quelque chose de simple comme ça, mais j'essaie vraiment d'apprendre autant que possible car je sais qu'il y a de grands avantages avec Clojure tels que l'utilisation de refs...

J'apprécierais vraiment que quelqu'un puisse m'aider. Merci!!

23
demandé sur kuporific 2012-04-02 22:39:55

2 réponses

Une façon de traduire une boucle for impérative en Clojure est d'utiliser la macro for.

(for [i (range 10)] (inc i))

La fonction ci-dessus renverra tous les nombres de 0 à 9 incrémentés de 1. Cependant, il semble que vous souhaitiez simplement itérer sur une collection séquentielle et utiliser chaque élément. Si c'est tout ce dont vous avez besoin, vous n'avez pas besoin de référencer une valeur d'index, vous pouvez plutôt référencer chaque élément directement.

(for [d my-vec-of-data] (my-function d))

Cependant, pour ce cas simple, la fonction map serait probablement une meilleur choix car il est conçu pour appeler des fonctions avec des arguments à partir de collections. L'exemple suivant est équivalent à l'utilisation de for ci-dessus.

(map my-function my-vec-of-data)

Les deux map et for renvoient une collection de valeurs composée des valeurs renvoyées par my-function. C'est parce que les structures de données de Clojure sont immuables, il est donc nécessaire d'avoir une nouvelle collection retournée. Si ce n'est pas ce dont vous avez besoin ou si votre fonction a des effets secondaires, vous pouvez utiliser doseq au lieu de for, qui renvoie nil.

34
répondu Jeremy 2013-12-04 10:32:54

La réponse de Jeremy est bonne pour savoir comment faire une boucle for dans Clojure idiomatique.

Si vous voulez vraiment un style impératif pour la boucle dans Clojure, vous pouvez en créer une avec cette macro:

(defmacro for-loop [[sym init check change :as params] & steps]
 `(loop [~sym ~init value# nil]
    (if ~check
      (let [new-value# (do ~@steps)]
        (recur ~change new-value#))
      value#)))

Utilisation comme suit:

(for-loop [i 0 (< i 10) (inc i)] 
  (println i))
33
répondu mikera 2012-04-07 17:33:53