Он никогда не вернется, потому что Reduce принимает последовательность и функцию и применяет эту функцию до тех пор, пока входная последовательность не станет пустой , только тогда она сможет узнать, что имеет окончательное значение.
Reduceна действительно бесконечном seq не будет иметь большого смысла, если он не производит побочный эффект, такой как регистрация его прогресса.
В первом примере вы сначала создаете переменную, ссылающуюся на бесконечную последовательность.
(def c (cycle [0]))
Затем вы передаете содержимое переменной var, чтобы уменьшить, что начинает чтение элементов для обновления его состояния.,
(reduce + c)
Эти элементы нельзя собирать, поскольку переменная c содержит ссылку на первый из них, который, в свою очередь, содержит ссылку на второй и так далее.В конце концов он читает столько места, сколько есть места в куче, а затем - OOM.
Чтобы не допустить переворота кучи во втором примере, вы не сохраняете ссылку на данные, которые вы уже использовали, поэтому элементы наПоследовательность, возвращаемая циклом, GCd так же быстро, как они создаются, и накопленный результат продолжает увеличиваться.В конечном итоге он переполнится долго и потерпит крах (clojure 1.3) или превратится в BigInteger и вырастет до размера всей кучи (clojure 1.2)
(reduce + (cycle [0]))