2015-05-17 5 views
5

Когда я бегу (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 .................... 

Мои ожидания, когда я запускаю код, который РЕПЛ ничего не показывает и просто застрял, потому что (iterate inc 0) никогда не заканчивается. Но, я вижу (0 1 2 3 ....

(iterate inc 0) генерирует бесконечную последовательность, которая никогда не возвращается. Если это никогда не закончится, то почему println начинает печатать значения?

Иными словами, почему началось вычисление (println xx), даже если входной сигнал никогда не заканчивается?

+1

'println' не нужна вся последовательность будет реализован перед печатью , он делает это по требованию. «который никогда не возвращается». '(first (iterate inc 0))' вернет вам '0' по той же причине. – zerkms

ответ

8

Вы должны прочитать на в Clojure. Они могут создавать значения, которые могут потребляться постепенно, до того, как будет реализована вся последовательность (что в этом случае никогда не произойдет).

Это может помочь подумать об этом как о том, как нажать и вытащить. Вместо того, чтобы итерации создавать весь список значений, а затем подталкивая их к функции println (чего никогда не будет), повторяйте просто руки, это ленивая последовательность, а println тянет значения по мере необходимости. Вот почему (возьмите 5 (iterate inc 0)) работает; возьмите только попытки вытащить 5 значений перед остановкой.

2

Печать Clojure умнее, чем System.out.println; это может быть customized for different types. В случае последовательностей это walks through element-by-element, printing each one as it goes - нам не нужно ждать, пока вся последовательность будет оценена, чтобы начать печатать вещи.

В отличие от этого, System.out.println, который вызывает перед печатью toString, ведет себя как можно скорее. Он зависает вечно, а не печатает ничего, потому что toString нуждается в оценке всей последовательности - или, по крайней мере, она зависала бы навсегда, если бы не закончилась память, пытаясь построить строку.

Тем не менее, все выражение действительно застрял - если вы ждали его, чтобы остановить печать, вы бы ждать вечно:

(do 
    (println (iterate inc 0)) 
    (println "Never reached!"))