On Fri, Jan 4, 2013 at 9:02 AM, Edward Tsech <edts...@gmail.com> wrote:

> Thanks Dave! Seems like different people expect slightly different
> behavior.


Are we reading the same thread?  When I looked at it, it seemed that there
was actually very broad consensus about the desirability of multiple
bindings in when-let/if-let and about the behavior.  Nearly everyone agreed
it was obvious that as soon as you hit a variable that is bound to nil, you
bail out of the expression, short-circuiting further evaluations and
returning nil (for when-let) or the else clause (for if-let).

There were a few quibbles about what variables should be bound in the else
body of an if-let, but it doesn't really matter too much.  As long as a
choice is made and it is documented, it will be an improvement over not
allowing if-let bindings.

WHY IT MATTERS

One problem I'm always trying to combat is that Clojure code tends to get
deeply indented, with lines of code starting halfway across the page.  This
makes code hard to read, understand, and maintain.  One of the biggest
culprits is let.  In mainstream programming languages, creating local
variables does not add to the indentation/nesting level of the code.  Note
that when F# went mainstream, one of the first changes they made to ML
syntax was to get rid of the nesting introduced by let.   The problem gets
even worse when you have a series of if/cond and lets.  This happens a lot
because it is normal in Clojure for functions to return a value or nil, and
those nils need to be guarded against.  if-let and when-let help you combat
the indenting, by combining one pair of if/let, effectively halving the
amount of indentation for code that is nested in this way.  But because
they can only fuse one pair of bindings at a time, those forms are not
nearly as useful as they could be.

WHY THIS HASN'T CHANGED (speculation)

Broadly speaking, if you have a chain of computations, there are two
different styles for structuring this in Clojure.  One option is a series
of lets.  The other option is to use threading forms (->, ->>, etc.).

I speculate that the core team have a preference for the threading forms.
This is evidenced by the fact that one of the two major additions announced
for 1.5 is the new threading forms.

Frankly, I remain baffled by the popularity of the threading macros because
they have several significant limitations.

The biggest limitation is that they are only useful when you apply a
sequence of functions to the previous result in a way that the previous
result is always the first input, or always the last input.  Since
Clojure's built-in functions sometimes expect the collection as the first
input and sometimes as the last, as your chain gets longer it becomes
increasingly unlikely that one of the threading macros will be relevant.
This wouldn't be such a limitation if you could use anonymous functions
among the chained functions (since then you could set up a function with
the "hole" anywhere you want), but this doesn't work.  So if you have a
series of threaded computations, and then need to go back and add a
function that doesn't share the first-arg/last-arg preference of the other
computations in the chain, you're out of luck and need to refactor.

One thing I've always liked about the let form over threading is that it
allows you to give names to your intermediate computations.  Well-chosen
names can make your code significantly clearer and easier to understand.
And of course, sometimes, you really need to name the intermediate
computations.  (One of the new threading macros is a mechanism for patching
this limitation, allowing one to create an intermediate name within the
threading, albeit with a somewhat confusing, indent-inducing new macro to
be used inside of the threading macro).

I find threading macros to sometimes be a succinct way to represent a chain
of 3 or 4 computations where the first-argument/last-argument align and I'm
confident that I won't be adding other functions to the chain later, but
anything beyond that, I feel the limitations outweigh the benefits.

Despite that little rant, I don't begrudge the folks who love the threading
macros and are looking forward to the expansion of the "threading DSL" in
the new version.  Different people have different stylistic preferences,
and that's fine.  However, I'm disappointed that the if-let/when-let camp
hasn't seen more love.

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

Reply via email to