Question

I'm wondering how to force a lazy sequence of functions to be evaluated.

For example if I have a function that returns the integer 1:

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

And I construct a lazy sequence of these functions:

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

How do I actually execute the functions in the sequence?

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

I've read through How to convert lazy sequence to non-lazy in Clojure , which suggested doall...but I'm not sure where the results are going? I'm expecting [1 1 1 1 1] or something similar.

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
Was it helpful?

Solution

Your problem is that you are returning a sequence of un-evaluated functions. You can evaluate them as follows:

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

Both map and repeat are lazy, but the REPL or any other consumer forces the evaluation of at least as much of a lazy sequence as it needs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top