Как сделать цикл for в Clojure?

Я изучаю немного Clojure и использую Quil. Я хотел бы знать, как перевести цикл for в Clojure:

Вот как я бы сделал это на Java или похожих языках:

for ( int i = 0; i < numSides; i++ ) {
    float posX = cos( theta * i );
    float posY = sin( theta * i );
    ellipse( posX, posY, polySize, polySize );
}

Моя попытка Clojure:

  (let [theta (/ PI num-sides)
        angle (range 0 num-sides)
        pos-x (cos (* theta angle))
        pos-y (sin (* theta angle))]
    (dorun (map #(ellipse % % % %) pos-x pos-y poly-size poly-size)))

4 ответа

Решение

Все способы, которые вы искали, в основном работают с последовательностями, где в качестве цикла речь идет о выполнении вещей определенное количество раз. Clojure предоставить dotimes делать вещи определенное количество раз:

(dotimes [i 10]
  (println i))

Таким образом, ваш код становится примерно таким:

 (dotimes [i num-sides]
   (let [pos-x (cos (* theta i))
         pos-y (sin (* theta i))]
         (ellipse pos-x pos-y poly-size poly-size)))

Если вы действительно хотите C-стиль for loop, то в моем libj clojure-utils есть удобный макрос for-loop, который позволяет вам делать такие вещи, как:

(for-loop [i 0 , (< i num-sides) , (inc i)]
  ... do stuff.....)

Обычно, однако, я обнаружу, что использую одно из следующего:

  • (dotimes [i num-sides] ....) - сделать что-то определенное количество раз
  • (doseq [x some-sequence] ....) - сделать что-нибудь для каждого элемента в последовательности
  • (for [i (range n)] ...) - построение списка из n элементов

Возможно, это несколько академично, но мне нравится использовать Clojure "для понимания" для такого рода вещей. Код будет выглядеть так:

(dorun
  (for [i (range num-sides)
        :let [pos-x (Math/cos (* i theta))
              pos-y (Math/sin (* i theta))]]
    (quil.core/ellipse pos-x pos-y poly-size poly-size)))

Doseq с range часто подходит для зацикливания определенного количества значений с целью создания побочных эффектов. Я бы реализовал ваш цикл следующим образом:

(doseq [i (range 0 num-sides)]
  (ellipse (cos (* theta i)) 
           (sin (* theta i)) 
           poly-size 
           poly-size))
Другие вопросы по тегам