I have this set of functions - it works, but I'm concerned about the use of lets.
(defn- create-counts [coll]
"Computes how many times did each 'next state' come from a 'previous state'.
The result type is {previous_state {next_state count}}."
(let [past coll
present (rest coll)
zipped (map vector past present)
sorted (sort zipped)
grouped (group-by first sorted)
seconds (map (fn [[key pairs]] [key (map second pairs)]) (seq grouped))
freqs (map (fn [[key secs]] [key (frequencies secs)]) seconds)]
(into {} freqs)))
I started learning functional programming in Haskell some time ago, and there, because of laziness, it's commonplace to use this equivalent of Clojure let, because what's not needed, isn't ever computed:
asnwer = z
where
notused = map (^1000) [1000..10000]
x = [1..]
y = take 10 x
z = map (*2) y
- Is it okay to use Clojure
letin this way? Look for example at thecreate-countsfn definition - I use it quite heavily there. - Would it be better to just put it all inside one expression?
- What's the best practice for this?
I like how everything's named, but I don't know if there's not a performance penalty hidden somewhere.
When I try to match the Haskell example with Clojure code, it seems there's eager evaluation:
(let [notused (do (Thread/sleep (rand 10000000)) :done)
x (iterate inc 1)
y (take 10 x)
z (map #(* 2 %) y)]
z)
;=> sleeps till the judgement day
I could imagine preventing this with futures or some clever let-like macro, but really it seems to me that I'm trying to do something Haskell-y (lazy) in Clojure. What's the idiomatic way?
letislet.whereis a different beast – jozefg Feb 25 at 0:36