

Why Clojure? - DanielRibeiro
http://thecleancoder.blogspot.com/2010/08/why-clojure.html

======
Raphael_Amiard
Î really love clojure, but this article is _not_ a good plaidoyer, for a lots
of reasons, the first and most pregnant being the ability of the author to
vastly traverse subject he is probably not an expert about.

> Functional programming, of the kind shown in SICP, is a way to write code
> that does not manage the state of variables, and could therefore be
> partitioned to run in parallel on as many processors as you like

This is kind of true, but totally misleading, because very few tasks are
actually easily paralelizable this way. When you stumble on one, you know it,
and replacing map with pmap certainly _is_ a joyful exercise, but this kind of
parallelization are easy to do in __any __languages. The hard parts are those
when you need to access shared state across threads. The facilities that
clojure provide in this respect, while innovative and enlightening , have
benefits that largely remain to be proven.

> languages like F# and Scala which have a complexity and "quirkiness"
> reminiscent of C++

Erm, sorry, what, F# reminiscent of C++, did you even try to read some code
written in F# ? F# has one of the tersest syntax you're likely to find in any
language. As an ML descendant it does already have a very clean syntax, and
the addition of significant whitespace only adds to that.

> You can write Clojure code that derives from Java classes and overrides Java
> methods. In short, if you can do it in Java, you can do it in Clojure.

Yeah sure, but in practice, most people that says that didn't ever had to
_really_ handle a non trivial project with java interaction in it. I did. And
frankly it can get ugly. It's good to have it, but ideally, all should be
encapsulated in idiomatic clojure wrappers. While this is not that hard
because java interaction is very well thought, it's a long and boring process,
and when you're in the middle of a project and just needs some bit of
functionnality that isn't in a clojure lib (and trust me there are still a lot
of those), you tend to just use the java interop in place. And then you get
back and read your code, and you cry.

In short, this is just a rehashing of what you usually hear about clojure, but
with no insight of real use. My (uninformed) guess, is that the author
probably didn't use clojure a lot, and frankly, this kind of stereotyped talk
gets old.

~~~
swannodette
Your response is more misleading than the article:

 _> but this kind of parallelization are easy to do in any languages._

Not if you have a GIL. Even then the languages without that limitation do not
make what pmap does ... easy.

 _> [STM] have benefits that largely remain to be proven._

I always find this statement to be misleading. STM has been shown to greatly
benefit the _correctness_ of concurrent programs, you're managing that less by
hand. The only thing that seems to be unproven is whether the performance
tradeoff is worth it. It'd be nice to see some numbers that show what you lose
in X% of the performance vs removing X% the amount of locking code.

 _> [Java interop] And frankly it can get ugly. It's good to have it, but ..._

Yet far less tedious and simpler than writing a C module, or a C library
binding. If you're comparing against that, Clojure's Java interop story is
damn heavenly.

 _> In short, this is just a rehashing of what you usually hear about clojure,
but with no insight of real use ..._

Perhaps for you and I. But there are a lot of people in this big wide world.
Uncle Bob taps into a community that's quite different from the language
enthusiast crowd of HN.

Your viewpoint more myopic than the OP. Yet you get upvotes. Oh well.

~~~
Raphael_Amiard
>Your response is more misleading than the article

Well maybe, but i feel like you are purposedly misunderstanding me. This was
not a rant about clojure, but about the article, yet you take my quotes out of
their original context and make it seem like so.

> Not if you have a GIL.

Ok, fair point. But that's not the question. The OP was claiming functionnal
programming made parallelization a breeze, which is a very stereotypical
position you hear a lot lately. Well, the kind of parallelization which is
made a breeze by FP is also the kind that is very easy, not in any language,
but in any language claiming to have parallelization features, cf. delirium's
answer.

> Yet far less tedious and simpler than writing a C module, or a C library
> binding

Okay, i was merely reacting to the claim that "anything you can do in java you
can do in clojure". Which, for taking your comparison, would be like saying
"anything you can do in C you can do in Python". Okay not exactly like that,
but the fact remains. The impression the OP gives in this regard is that ,
since there is this java interop, the library problem is solved. Well no, it
is not, and very far from it. If this kind of bullshit marketing talk went
away, you'd see less newbies complaining in #clojure or on the group about how
it's hard to do X.

> Uncle Bob taps into a community that's quite different from the language
> enthusiast crowd of HN.

But i'm commenting on HN, not on his blog. This is for a reason. I'm judging
the interrest of the article relatively to the crowd here.

On a side note, i did not even notice it was Uncle Bob. If i had, my rant
would have been even worse, or i would not had written it maybe. It does
indeed exhibit the same emptyness i feel from every of his articles. Maybe
it's a good article, and i'm overly critical, and i should probably try and
write my own article about why i love clojure, to realize it's not necessarily
that easy. But i have a very bad reaction to marketing talk.

------
cageface
You know, I really _want_ to like Clojure, but so far I'm finding it a bit of
a slog, for the following reasons:

1\. stack traces are very hard to decipher

2\. ubiquitous laziness can lead to some really subtle bugs

3\. the syntax can be extremely obtuse, moreso than other lisps

4\. the basic ADT is just a keyed map, which provides a lot of flexibility but
also can make data modeling very opaque, even compared to other dynamic
languages

5\. immutable and recursive as a default takes a lot of getting used to.
things I could dash out in minutes in ruby take me hours sometimes

6\. other languages have caught up enough that Lisp macros are not as game
changing as they might have been ten years ago

I embarked on a project recently to explore machine learning algorithms,
implementing them in both Scala and Clojure at the same time. I expected this
to be an easy win for Clojure but, to my surprise, I'm _much_ more productive
in Scala, my code has fewer bugs, and I can refactor it much more
aggressively. I realize that this isn't an either/or thing and it may be
entirely my shortcomings at play here, but my instinct is that although
Clojure is a superb lisp, it's still a lisp, and it's going to be a niche that
most programmers won't choose to occupy.

~~~
jimbokun
"2. ubiquitous laziness can lead to some really subtle bugs"

I find myself implementing Iterable wrappers more often in Java now, largely
due to the influence of Clojure lazy seqs. Then I can use the abbreviated for
loop syntax, for example, without creating a ridiculously large ArrayList in
memory.

I know that the Iterator pattern has been around for a long time, but I never
realized how broadly it could be applied to use high level iteration
constructs while keeping a minimal memory footprint, before I got used to
Clojure.

So Clojure has made me a fan of lazy evaluation, even in Java.

~~~
rdtsc
It is also very easy in Python:

Use generator list comprehensions:

    
    
        (x for x in xs)
    

instead of building the full list:

    
    
        [x for x in xs]
    

Use generators instead of plain functions when you can.

Learn to use itertools module: <http://docs.python.org/library/itertools.html>

I use these often:

    
    
        * chain()
        * imap()
        * groupby()
        * takewhile()
        * tee()
        * izip()
        * izip_longest()
        * permutations()
    

You can make you code quite "lazy" if you practice enough, and eventually it
just becomes a habit. Whenever you do anything you start asking yourself :
"can I do this in a lazy way?"

~~~
weavejester
Iterators in Python are slightly different from lazy lists in languages like
Haskell and Clojure. In Python, iterators are stateful; calling next() moves
the iterator on, discarding the previous head. In Clojure, a seq has no state,
and the head is not automatically discarded when the next item is accessed.

------
mhd
I wish someone would take the compiler infrastructure of Go and would make
native Clojure with it, with an easy access to C instead of Java. I need a
good exit path from things like Java, not something to just ease the pain.

~~~
bitdiddle
If I recall correctly this was one of the goals of Guile, which is essentially
Scheme, arguably cleaner than common lisp.

~~~
mhd
I won't get into the CL vs. Scheme pissing contests, but if I remember
correctly Guile was basically RMS' answer to Tcl, a language he didn't
particularly like. And it was more intended to replace Emacs Lisp, while most
of the infrastructure would still be written in C. Running on Hurd, of course.

~~~
bitdiddle
That sounds correct, but also embeddable and callable from C. It's unfortunate
it didn't succeed in replacing elisp. Emacs would be even more awesome than it
is today.

I'd love to see the same thing done with Clojure and Go.

~~~
mhd
I'd much rather have a proper, powerful Lisp than being forced to settle on
alternate soft and hard layers. But the Common Lisp Emacs project never went
anywhere.

------
Zak
Great article overall, but it makes the same mistake as many other Clojure
overviews: implying that STM is the only means of managing state. Clojure, in
fact has four main ways to do state, one of which is a (thread-local) normal
variable. Each is appropriate for a different sort of stateful operation; STM
is the most complicated.

~~~
Raphael_Amiard
It is not a great article overall. It is well written, and conveys a lot of
enthusiasm, but has no insightfull/new content in it. I've read every clojure
news and article for six months, and this just basically rehashes every "I
love clojure article" i ever read.

~~~
bitsai
If you've been devouring every bit of Clojure-related writing (which I've also
been trying to do), then as swannodette said to you elsewhere on this page,
you very well may not be the intended audience :)

------
nkh
I agree with the article, and I have to admit I think Rich Hickey (creator of
Clojure) is a brilliant man. If you check into his thoughts on programming you
will find some very interesting arguments. His talk on state and identity:
[http://www.infoq.com/presentations/Are-We-There-Yet-Rich-
Hic...](http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey) is
awesome, and I can not recommend highly enough.

If you want motivation for learning a lisp (Clojure is one) check out
<http://www.paulgraham.com/avg.html> if you have not already done so. An
awesome essay to re-read if you have not done so in a while.

Edit: Fixed Link (thanks atuladhar)

~~~
jules
Can you explain the point he is making in "Are we there yet"? I have watched
it but I didn't really get a different viewpoint on state and identity. That
could be because I already had the same viewpoint, but I doubt that.

~~~
nkh
The text below is directly lifted from the Clojure site at:
<http://clojure.org/state> The article describes it more clearly and
succinctly then I could.

There is another way, and that is to separate identity and state (once again,
indirection saves the day in programming). We need to move away from a notion
of state as "the content of this memory block" to one of "the value currently
associated with this identity". Thus an identity can be in different states at
different times, but the state itself doesn't change. That is, an identity is
not a state, an identity has a state. Exactly one state at any point in time.
And that state is a true value, i.e. it never changes. If an identity appears
to change, it is because it becomes associated with different state values
over time. This is the Clojure model.

~~~
jules
So is he saying that you should not nest refs? i.e. you should not create a
vector of refs and assign the vector to a ref. Because now the state itself
can change.

------
edanm
Not sure I'll have time to check out Clojure any time soon, but this post
convinced me I want to read SICP. Despite hearing great things about it, my
impression was always that it was much better for beginners, and wouldn't
teach me _that_ much. Sounds like I was wrong.

~~~
zsouthboy
The entire book is available on their website: <http://mitpress.mit.edu/sicp/>

Wanted a deadtree version to read at my leisure, but at $70 I think I'll read
the HTML version.

EDIT: found a PDF version: [http://www.scribd.com/doc/15556326/Structure-and-
Interpretat...](http://www.scribd.com/doc/15556326/Structure-and-
Interpretation-of-Computer-Programs-SICP)

~~~
atuladhar
There are used copies available on Amazon (and elsewhere too, I'm sure) for
about $40. Recycle, guys!

~~~
jules
Honest question: does it take less energy to ship the book across the ocean or
to print a new one (with a home laser printer and ordinary paper).

------
mattwilliams
Bob's Railsconf 2010 talk, "Twenty-Five Zeros", is also worth a watch if you
enjoyed this post of his.

<http://www.youtube.com/watch?v=mslMLp5bQD0>

------
bitsai
Excellent. Since picking up (and falling in love with) Clojure a few months
ago, I've had multiple "Why Clojure?" discussions with friends and co-workers.
This post is short, sweet, and hits all the points I've tried to make (poorly)
to others. Saving it now as ammunition for the next "Why Clojure?" discussion
:)

------
linuxhansl
I will be forever grateful, that my University taught Scheme/Lisp with this
book (and others) as introduction to programming.

While I have never used Lisp or Scheme in my professional life, that set of
undergrad courses more or less defined my mindset when it comes to algorithms
and their expression and has lasted to the present day (some 20 years later).

~~~
dasil003
Agreed. I went to the University of Minnesota which modeled its curriculum
after the MIT CS program. I was saddened to hear they were ditching Scheme for
their intro class. I don't see why they felt the need to update to a more
"modern" language. It's impossible for any language to ever more directly
express the basic concepts of functions and recursion than lisp. Why muddy the
waters with syntax?

------
kunley
I guess there's an established trend how one writes about switching to new
language: it's usually a long blog post containing facts distilled by others,
sometimes mixed with author's wishful thinking. All that because author
probably feels a need to justify his decision.

It's normal - we usually want to justify the reasons why we do stuff, esp.
when the new way is time consuming. It's also great that the OP is willing to
dive into new waters. But such article cannot be taken as an expertise, even
for the reason that it's not from OP's experience (yet).

------
limist
A more complete and detailed answer to this article's question is provided by
the free Chapter 1 of Amit Rathore's book-in-progress, Clojure in Action:

<http://www.manning.com/rathore/>

As Rathore puts it, Clojure's power is drawn from three mutually supportive
design decisions: 1) it's a Lisp, 2) it's functional, and 3) it's on the JVM.
Read Chapter 1, it's well written.

------
dasil003
I've never more than dabbled in the functional programming world. I've been
pretty happy professionally in Ruby for the last 5 years. However, if there's
one thing that I learned, it's that unit testing is an invaluable sanity check
but a poor substitute for mathematical rigor.

I see my trajectory over the next 5 years to involve learning Haskell well
enough to know the functional approach for a much wider set of problems, but
then falling back to Clojure professionally because, you know, I gotta get
shit done.

~~~
gaius
Unit testing is a poor substitute for strong typing in this context.

~~~
dasil003
and purity.

------
almost
Anyone have any recommendations for trying Clojure? I'm an Emacs user on
Ubuntu and I'd like to try it out but there seems to be quite a lot of choice
about how you do things I'm a bit lost.

Any up to date blog posts on setting up Clojure and connecting Slime to it?
The ones I've found are always slightly out of date (apparently starting swank
from Emacs isn't the preferred way to do it anymore?)

~~~
arete
Yeah there are a bunch of different ways to start Clojure with a REPL and/or
swank server running. Maven, Leiningen, and cake are all build tools that also
do dependency management - great when you're working on a complex project but
have some amount of setup overhead for their project descriptors. cljr is a
different option that lets you start a REPL anywhere, with no project
descriptor, and also takes care of setting up your JVM classpath with any
dependencies you've installed via 'cljr install'.

All of these tools encourage running the JVM outside of emacs, rather than as
an inferior-lisp, and have some command line option that starts a swank server
on a specified port. After that you can just do M-x slime-connect and get
hacking as usual =)

------
sqrt17
> become enamored with a language that has roots that go back to 1957, i.e.
> Lisp?

Duh. What does that punk think that the "60" in Algol 60 stands for? Y'know,
the bondage and discipline languages also have an ancestry that goes pretty
far back.

And I'd choose C++ (or Java) over Algol just as I'd choose Clojure over
Lisp1.5 any time.

------
jules
I'm eagerly awaiting the binary release of ClojureCLR.

------
herdrick
... _any time a Clojure programmer want's to change the state of a variable,
they must do so using the same kind of transaction management as they would
use for a database._

Not a good thing. The word 'must' is the glaring red flag.

~~~
ihodes
It _is_ a good thing.

And it's as simple as e.g. (dosync (ref-set ref newval)). In fact, if you find
yourself doing it a _lot_ (don't, please!) then define yourself a little
function (defn rset [r v] (dosync (ref-set r v))).

Must isn't that bad of a word, and it's a Lisp: what kind of boilerplate do
you expect to write? I prefer it going on none.

It's definitely worth checking out, and if you need state, and you'll need it
rarely if at all, you're better served using the built-in STM and the
wonderful functions that allow you to manage it (like _add-watch_ ; what a
lifesaver in a state-heavy app like a GUI) to handle the mess.

~~~
herdrick
I don't understand you. If you don't like to write boilerplate, why do you
appreciate Clojure making mutation verbose?

There are times when the imperative style is more natural.

~~~
herdrick
_I don't understand you._

By this I merely meant, "I don't understand what you are saying". Hope that
was clear.

------
c00p3r
only when pg will use it.. =)

~~~
c00p3r
Hey, what's wrong? It is so cool and modern Lisp implementation which runs on
even more cool and super-efficient JVM (who said Ernang?!), so, why not?!
Let's port HN news app to Clojure and see how much users it can handle. Every
one know that Jetty is so cool! ^_^

------
jsmcgd
Because it's so clean.

------
knodi
I don't think so I'll take erlang over clojure any way.

