Clojure: идиоматический способ повторения со значениями, основанными на условных выражениях

Поскольку recur может использоваться только в хвостовой позиции, как мне повторить со значением, которое зависит от вложенных условных выражений? Вот пример:

(loop [a (rand-int) b 0]
    (if (< a 300)
       (recur (rand-int) 1))
    (if (a < 10000)
       (recur (rand-int) 5))
    b)

Проблема в том, что рекурсы не происходят в хвостовой позиции. Итак, как мне выполнить цикл с новым значением, которое зависит от внутреннего условия. Я мог бы сделать ссылку и поменять ее местами в условных выражениях, а затем повторить в хвостовой позиции, но есть ли способ сделать это без мутации значения?

1 ответ

Решение

Все рекурсы могут быть в хвостовой позиции:

(loop [a (rand-int 20000) b 0]
    (if (< a 300)
       (recur (rand-int 20000) 1)
       (if (< a 10000)
         (recur (rand-int 20000) 5)
         b)))

Или, возможно, немного более читабельным:

(loop [a (rand-int 20000) b 0]
  (cond 
    (< a 300)   (recur (rand-int 20000) 1)
    (< a 10000) (recur (rand-int 20000) 5)
    :default    b))
Другие вопросы по тегам