лень не работает должным образом

(defn seq-trial
  []
  (map #(do (println "hello " %) (inc %)) (range 10)))

(take 3 (seq-trial))

Приведенный выше фрагмент кода при оценке распечатывает следующее:

(привет 0 привет 1 привет 2 привет 3 привет 4 привет 5 привет 6 привет 7 привет 8 привет 9 1 2 3)

Поскольку карта возвращает ленивую последовательность, я ожидал, что это будет только печатать -

(привет 0 привет 1 привет 2 1 2 3)

Почему здесь оценивается весь список?


person Pranav    schedule 07.03.2013    source источник


Ответы (1)


Это связано с оптимизацией производительности, называемой фрагментированием. По сути, последовательность реализуется группами по n элементов, называемых порциями. Это означает, что вам нужно позаботиться о любых побочных эффектах в вашей функции отображения. Конечный результат правильный, но вы все равно получите последовательность верной длины.

Размер блока по умолчанию - 32, поэтому, если вы увеличите свой диапазон до значения, большего, чем это, вы поймете, что происходит, немного лучше:

user> (defn seq-trial
  []
  (map #(do (println "hello " %) (inc %)) (range 100)))

user> (take 3 (seq-trial))
hello  0 ; 32 item 'chunk' realized...
hello  1

...

hello  30
hello  31
(1 2 3)  ; the expected returned value

Если вам нужно избежать фрагментов, есть доступны варианты

person sw1nn    schedule 07.03.2013
comment
Побочные эффекты и ленивая оценка несовместимы. - person Don Stewart; 07.03.2013