In clojure, this is valid:
(loop [a 5]
(if (= a 0)
"done"
(recur (dec a))))
However, this is not:
(let [a 5]
(if (= a 0)
"done"
(recur (dec a))))
So I'm wondering: why are loop and let separated, given the fact they both (at least conceptually) introduce lexical bindings? That is, why is loop a recur target while let is not?
EDIT: originally wrote "loop target" which I noticed is incorrect.
Consider the following example:
(defn pascal-step [v n]
(if (pos? n)
(let [l (concat v [0])
r (cons 0 v)]
(recur (map + l r) (dec n)))
v))
This function calculates n+m
th line of pascal triangle by given m
th line.
Now, imagine, that let
is a recur
target. In this case I won't be able to recursively call the pascal-step
function itself from let
binding using recur
operator.
Now let's make this example a little bit more complex:
(defn pascal-line [n]
(loop [v [1]
i n]
(if (pos? i)
(let [l (concat v [0])
r (cons 0 v)]
(recur (map + l r) (dec i)))
v)))
Now we're calculating n
th line of a pascal triangle. As you can see, I need both loop
and let
here.
This example is quite simple, so you may suggest removing let
binding by using (concat v [0])
and (cons 0 v)
directly, but I'm just showing you the concept. There may be a more complex examples where let
inside a loop
is unavoidable.
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