If I am returning a lazy-seq from a function like this:
(letfn [(permutations [s]
(lazy-seq
(if (seq (rest s))
(apply concat (for [x s]
(map #(cons x %) (permutations (remove #{x} s)))))
[s])))])
If I use loop recur like below, will the list be eagerly evaluated?
(loop [perms (permutations chain)]
(if (empty? perms)
(prn "finised")
(recur (rest perms))))
If it is eagerly evaluated, can I use loop..recur to lazily loop over what is returned from the permutations
function?
The list is lazily evaluated by your loop-recur code.
You can try it out yourself. Let's make permutations
print something every time it returns a value by adding a println
call.
(defn permutations [s]
(lazy-seq
(if (seq (rest s))
(apply concat (for [x s]
(map #(cons x %) (permutations (remove #{x} s)))))
(do
(println "returning a value")
[s]))))
When using loop
, let's also print the values with we're looping over with (prn (first perms)
.
(loop [perms (permutations [1 2 3])]
(if (empty? perms)
(prn "finised")
(do
(prn (first perms))
(recur (rest perms)))))
Here's what it prints:
returning a value
(1 2 3)
returning a value
(1 3 2)
returning a value
(2 1 3)
returning a value
(2 3 1)
returning a value
(3 1 2)
returning a value
(3 2 1)
"finished"
As you can see, "returning a value" and the value lines are interlaced. The evaluation of the lazy seq can be forced with doall
. If you loop over (doall (permutations [1 2 3]))
, first it prints all the "returning a value" lines and only then the values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With