I have:
(defn keep?
(def sum [])
(loop [i 0]
(when (< i 10)
(conj sum 10)
(recur (inc i))))
sum
)
This just gives me and empty vector even though I am conj-ing 10 onto sum. Is this because it is not in-scope within the Loop? How would I achieve the same outcome. (btw, this example is deliberately simplified)
Thanks
conj
does not modify its argument. In fact, without resorting to evil reflection tricks, nothing will modify a vector, it's an immutable data structure. This is one of the fundamental principles of Clojure.
In functional programming, instead of modifying data, we replace it with another immutable value. So you need to use the return value of conj
, or it is effectively a noop.
(defn keep?
[]
(loop [i 0 sum []]
(if (< i 10)
(recur (inc i) (conj sum 10))
sum)))
Also, the second arg to defn
must always be a vector.
conj
is not destructive, it does not alter that collection, returns a new collection with the designated state (reference).
To achieve the desired result, you may:
sum
in a loop
-form, like i
is defined, instead of using def
recur (inc i) (conj sum 10)
to rebind sum
to a new one on every iteration, so that state is built up to what you expectwhen
is not met, just return sum
from your loop
and it will bubble up to become the return value of this function. Uh hang on, when
does not have an "else-branch", a possible alternative is if
Like so:
(defn keep? []
(loop [i 0
sum []]
(if (< i 10)
(recur (inc i)
(conj sum 10))
sum)))
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