Lifting subexpressions up into lets is actually something I do a lot- for one very important reason: it lets me insert print statements (or logging statements) showing the value of the subexpression. So I'll do; (let [ x (subexpression) ] (main-expression))
because it lets me do: (let [ x (subexpression) ] (println "The value of x is" x) (main-expression)) If fact, a lot of times I'll do; (let [ x (subexpression) res (main-expression) ] res) because it lets me do: (let [ x (subexpression) _ (println "The value of x is" x) res (main-expression) ] (println "The value of the whole expression is" res) res) This is of great value in debugging. Brian On Tue, Oct 15, 2013 at 9:56 AM, Mikera <mike.r.anderson...@gmail.com>wrote: > I certainly prefer giving names to intermediate results with a "let" > block: having good names and breaking the computation up into logical > chunks makes the code much easier to understand and maintain when you come > back to it later. > > PG's example though is bad for different reasons - this is actually > mutating variables in an imperative style, which is definitely "bad style" > - both in Lisp and Clojure I think. The Clojure equivalent would be to use > atoms (or vars) and mutating them. > > "let" on its own is purely functional, and doesn't have this problem. > > > On Tuesday, 15 October 2013 20:29:29 UTC+8, Daniel Higginbotham wrote: >> >> I've been going through On Lisp by Paul Graham and on page 33 he >> recommends against performing "intermediate" bindings. Does this advice >> hold for Clojure? Here are a couple examples: >> >> ;; Common Lisp (from the book) >> (defun bad (x) >> (let (y sqr) >> (setq y (car x)) >> (setq sqr (expt y 2)) >> (list 'a sqr))) >> >> (defun good (x) >> (list 'a (expt (car x) 2))) >> >> ;; Clojure >> (defn bad [x] >> (let [y (first x) >> sqr (expt y 2)] >> (list 'a sqr))) >> >> (defn good [x] >> (list 'a (expt (first x) 2))) >> >> Paul Graham explains: >> >> "The final result is shorter than what we began with, and easier to >> understand. In the original code, we’re faced with the final expression >> (list 'a sqr), and it’s not immediately clear where the value of sqr comes >> from. Now the source of the return value is laid out for us like a road >> map. >> >> The example in this section was a short one, but the technique scales up. >> Indeed, it becomes more valuable as it is applied to larger functions." >> >> In clojure you can't do setq of course but I find myself going against >> this advice all the time, and I find that it's more important to do so when >> working with larger functions. I think introducing names makes code >> clearer. Here's an example from my own code: >> >> (defn create-topic >> [params] >> (let [params (merge params (db/tempids :topic-id :post-id :watch-id)) >> topic (remove-nils-from-map (c/mapify params mr/topic->txdata)) >> watch (c/mapify params mr/watch->txdata) >> post (c/mapify params mr/post->txdata)] >> {:result (db/t [topic post watch]) >> :tempid (:topic-id params)})) >> >> To my mind, creating bindings for "topic", "watch", and "post" makes the >> code easier to understand. When you get to "(db/t [topic post watch])" you >> don't have to deal with as much visual noise to understand exactly what's >> going into the transaction. >> >> So, is PG's advice any good? >> >> Thanks! >> Daniel > > -- > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > -- -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.