Following is the Clojure code:
(reduce (fn [r x] (if (nil? x) r (conj r x)))
[]
[:mouse nil :duck nil :lory nil])
In REPL, it evaluates to [:mouse :duck :lory]
.
My question is, how is the code evaluating?
According to me, r
is []
and x
is [:mouse nil :duck nil :lory nil]
. nil? x
is false as so it evaluates to (conj r x)
. But x is a vector, not an element so how it will add an element to the empty vector r in conj
? I don't know but I am wrong somewhere in my approach. The output is the animals' name vector without nil values.
Can anyone please explain me the execution of code. Thanks.
Your problem appears to be understanding how reduce
works. I'd like to refer you to the source code, but it simply maps onto a Java implementation, so I have to fake it.
The kind of reduce
you are doing - supplying the initial value - might have been coded as follows:
(defn reduce [f init coll]
(loop [acc init, tail coll]
(if (seq tail)
(recur (f acc (first tail)) (rest tail))
acc)))
As you can see, it works through the sequence coll
, applying the function f
to acc
and the first value in the sequence, to generate a new acc
. When there is no more sequence, it returns acc
.
How does this apply to your example? The reducing function ...
(fn [r x] (if (nil? x) r (conj r x)))
... ignores nil
x
s but conj
s anything else onto the end of the accumulating vector r
. Your code is more or less equivalent to ...
(remove nil? [:mouse nil :duck nil :lory nil])
=> (:mouse :duck :lory)
... except you get a lazy sequence instead of a vector.