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))