On 2013-10-15, at 8:29 AM, Daniel Higginbotham <nonrecurs...@gmail.com> 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)))

The closest I can think of to the bad CL code in Clojure would be something 
like:

(defn bad-clojure [x]
  (let [v (first x)
        v (Math/pow v 2)
        v (list 'a v)]
    v))   

I don't think anyone at all would find either the bad CL or Clojure code okay. 
This is more of an admonition to not be an idiot :-)

Your Clojure code is equivalent to the following CL code:

(defun good2 (x)
  (let* ((y (car x))
         (sqr (expt y 2)))
    (list 'a sqr)))

There's nothing wrong with writing code that way, it's functional and clear. 
What you're doing with this style of writing is introducing intermediate named 
values. Sometimes those just clutter up the code, sometimes they clarify. Use 
your own good taste. You'd do the same thing in Haskell, but I'd use a where 
clause.

> 
> 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."

Yes, in the bad CL code you don't know where the value of sqr comes from and 
the problem gets much worse as the code gets longer. This is the problem with 
imperative code in general.

You don't have that problem in either Clojure or the 'good2' CL program.

> 
> In clojure you can't do setq of course but I find myself going against this 
> advice all the time

He's not talking about intermediate names for values, he's talking about 
imperative assignments using setq, setf, and friends. Clojure's nearest 
equivalent, that I can think of, is shadowing in a let statement, and I think 
you'll find this is frowned upon.

> So, is PG's advice any good?

Yup.

Cheers,
Bob

> 
> 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.

Reply via email to