Выполнение ленивой последовательности функций

Мне интересно, как заставить ленивую последовательность функций быть оцененной.

Например, если у меня есть функция, которая возвращает целое число 1:

test.core=> (fn [] 1)
#<core$eval2480$fn__2481 test.core$eval2480$fn__2481@4163c61>
test.core=> ((fn [] 1))
1

И я строю ленивую последовательность этих функций:

test.core=> (repeat 5 (fn [] 1))
(#<core$eval2488$fn__2489 test.core$eval2488$fn__2489@76fd6301> ...)

test.core=> (class (repeat 5 '(fn [] 1)))
clojure.lang.LazySeq

Как я на самом деле выполняю функции в последовательности?

test.core=> (take 1 (repeat 5 (fn [] 1)))
(#<core$eval2492$fn__2493 test.core$eval2492$fn__2493@46e1e0c8>)

test.core=> (take 1 (repeat 5 '(fn [] 1)))
((fn [] 1))

test.core=> ((take 1 (repeat 5 '(fn [] 1))))

ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

Я прочитал, Как преобразовать ленивую последовательность в non-lazy в Clojure, которая предложила doall... но я не уверен, куда идут результаты? Я ожидаю [1 1 1 1 1] или что-то подобное.

test.core=> (doall (repeat 5 (fn [] 1)))
(#<core$eval2500$fn__2501 test.core$eval2500$fn__2501@14e3c50c>...)

test.core=> (realized? (doall (repeat 5 (fn [] 1))))
true

1 ответ

Решение

Ваша проблема в том, что вы возвращаете последовательность не оцененных функций. Вы можете оценить их следующим образом:

=> (map #(%) (repeat 5 (fn [] 1)))
(1 1 1 1 1)

И то и другое map а также repeat ленивы, но REPL или любой другой потребитель заставляет оценивать как минимум столько же ленивых последовательностей, сколько необходимо.

Другие вопросы по тегам