(println (iterate inc 0)): почему это даже начинает печатать?
Когда я бегу (println (iterate inc 0))
в моем ответе я получу что-то вроде этого:
user=> (println (iterate inc 0))
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 ....................
Когда я запускаю код, я ожидаю, что repl ничего не показывает и просто застрял, потому что (iterate inc 0)
никогда не заканчивается. А я вижу (0 1 2 3 ...
,
(iterate inc 0)
генерирует бесконечную последовательность, которая никогда не возвращается. Если это никогда не заканчивается, то почему println
начинает печатать значения?
Другими словами, почему (println xx)
начинает оцениваться, даже если ввод никогда не завершается при оценке?
2 ответа
Вы должны прочитать о ленивых seqs в Clojure. Они могут генерировать значения, которые можно использовать постепенно до реализации всей последовательности (что в этом случае никогда не произойдет).
Это могло бы помочь думать об этом как о толчке против тяги. Вместо того, чтобы повторять создание целого списка значений и затем помещать их в функцию println (что никогда не произойдет), выполняйте итерацию, просто передавая ленивую последовательность, и println извлекает значения по мере необходимости. Вот почему (возьмите 5 (iterate inc 0)) работает; take только пытается вытащить 5 значений перед остановкой.
Печать Clojure умнее, чем System.out.println
; это может быть настроено для различных типов. В случае последовательностей, он проходит по элементам, печатая каждую по очереди - нам не нужно ждать, пока вся последовательность будет оценена, чтобы начать печатать вещи.
В отличие от System.out.println
, который вызывает toString
перед печатью ведет себя так, как вы могли ожидать. Он висит навсегда, ничего не печатая, потому что toString
необходимо оценить всю последовательность - или, по крайней мере, она зависнет навсегда, если не будет исчерпано памяти при попытке построить строку.
Тем не менее, все выражение действительно застряло - если бы вы ожидали, чтобы оно прекратило печатать, вы бы ждали вечно:
(do
(println (iterate inc 0))
(println "Never reached!"))