One thing that I like let statements for is you can use them for "executable documentation", like this
(defn std-deviation [values])
(let [sum-of-values (reduce + values)
average-of-values (/ sum-of-values (count values))
deviations (map #(- % average-of-values) values)
deviations-squared (map #(* % %) deviations)
sum-of-deviations-squared (reduce + deviations-squared)
mean-of-deviations-squared (/ sum-of-deviations-squared (count deviations-squared))]
(Math/sqrt mean-of-deviations-squared))You can write this more concisely and/or elegantly, but the value of this style will come 3 months from now when you have to go in and fix something and you'd swear you've never seen this code before. But just by reading it, you can follow what each step is doing, even though there are no comments or docstrings.
I hope that math is at least close -- I've been travelling all week and I'm pretty bleary right now, but you get the idea.
BTW this question is definitely suited for the #beginners channel β you are making progress π
Definitely just a fluke, but thatβs good to know! Iβm going to a ClojureBridge event tonight, will try to recruit some more beginners to join me here.
@amelia let can also be used to avoid repeating code inside a function. We did this at the dojo event this evening in the function to rotate a sequence of numbers by a given distance.
(defn rotate [distance number-sequence]
(let [length (count number-sequence)
position (mod distance length)]
(drop position
(take (+ length position) (cycle number-sequence)))))
In this example we used length and position several times. Using let makes the code smaller and also avoids running the same code several times.