Как сделать цикл 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))