
What is Clojure good at? - bobobjorn
http://cleancode.se/2010/10/17/what-is-clojure-good-at.html
======
jrockway
Clojure is fine, but just to play devil's advocate:

 _First of all, the repl is a killer. This is not something that is unique to
clojure, but that doesnt make it less good. Beeing able to try out new api’s
and fumble forward is great._

You can do this with Java and every other language. There's even a C++ REPL
floating around out there. The real difference between Clojure (and CL, and
Haskell) is that there is a REPL culture -- library designers use a REPL, so
using one to play with their library feels natural. Trying using a C++ or Java
REPL and you'll find that... it's not so nice.

 _Second, there is no compile time. It is not that the compile time is short,
it doesnt [sic] exist._

Not correct. Fast compile time is always nice, and it's great that you don't
notice. But this statement is simply not technically correct.

 _Third, functions without state and side effects are alot [sic] easier to
test then [sic] java code. Yes you can still create hard to test code, but it
is harder._

But of course, nothing in Java forces you to use state and side effects. It's
a culture problem, again; but if you use Java libraries from within Clojure,
you are going to run into those same culture problems.

 _Fourth, you can abstract away more code._

This is true. Java is missing something like Perl's "roles" that allow you to
have code in interfaces. Imagine an "Equal" interface that defines equals and
not equals. In Perl, you can provide a default implementation for not equals
in terms of equals in Equals. In Java, well, I hope you like cut-n-paste or
messy delegation. (I have never seen a Java programmer do this, but here's the
pattern. Create a NotEquals class that has one parameter, a class that does
the Equals interface. Implement not equals by delegating to equals in the
object that was passed in. Now you have a class that can do equals and not
equals; so create an instance and delegate YourClass.not_equals to
NotEquals.not_equals. Now you can get not_equals without cut-n-paste. This is
too hard for most people to figure out, it seems.)

With a higher-level syntax, you can add Roles later, or automate the
delegation, so you can pick which design to use based on which one makes the
most sense, instead of which one means you have less boilerplate to cut-n-
paste. And that's the joy of high-level languages; you can write good code
without wearing out your fingers.

~~~
swannodette
_But of course, nothing in Java forces you to use state and side effects. It's
a culture problem, again; but if you use Java libraries from within Clojure,
you are going to run into those same culture problems._

This is a known problem. There is an in development feature called Pods that
will allow you to use nasty mutable Java libraries as well write your own
nasty Clojure mutable code (perhaps for performance reasons) w/o destroying
concurrency guarantees. I'm looking forward to see how it shakes out.

~~~
jrockway
Now I am beginning to understand why people like Clojure so much. Instead of
calling them "state threads", whose Google results turn up academic papers
from the early 90s, they call them "pods", whose Google results have nothing
to do with programming.

~~~
weavejester
Having a short name for commonly used structures aids readability. e.g.

    
    
        (ref {})
        (atom [])
    

Instead of:

    
    
        (software-transactional-memory-reference {})
        (atomically-mutable-reference [])

------
mr_luc
I sympathize with the author!

I had the same experience a couple of nights ago -- a corporate-programmer-
turned-manager friend (highly competent, Formally Trained in Dimensional
Modelling and Analysis using the Microsoft stack, etc) was asking me, with
some confusion, why I'd use a scripting language or any other 'out there'
language.

My first answers were, really, only good for someone who already knows what
the language features being described are. CL has macros, Ruby is dynamic and
the practice of using blocks ... what are those features, and what do they buy
you?

I could tell that my explanations were being parsed -- he's a very smart guy
-- but the parse tree was just being cached, with timeouts that would expire
long before compilation could take place.

So, I changed tactics -- like the author of this article.

"I like these languages because, look! I can type THIS instead of THIS!"

I kick myself now for not showing him some lisp, but I was working on a
ruby+sinatra app on my server in emacs in screen, so I brought up a repl and
showed him how few lines of code it took to make a class, and iterate through
a list, etc.

What stuck was showing the actual code handling signups in the (sinatra, so,
from-scratch) web app -- "look, 2 functions, 6 lines apiece, with error
handling and everything."

My friend has to manage programmers now, so he knows that (despite the
existence of libraries and frameworks and so forth) if you ask for someone to
make you an interface that does X, it's rare that you can get a 5-minute
turnaround. The productivity arguments carried the day(1).

"Look, I get to type less code than you, by far, every day!(2)" < \-- is a
quick way to get past whatever mental blocks the person has to considering
your language of choice.

And it sure ought to be easy to demonstrate if they're coming from C# or Java,
or what are you wasting your time on? ;)

\-----

(1) Unfortunately, he spent the rest of the night trying to pitch me on a
startup project of his own that he wanted help "implementing," because the
"lion's share" of the work, the data model, was done. But I digress.

(2) But with Ruby, it's easier to add "and look how easy it is to read!"
regardless of the background of your listener. Languages like Lisp, that
involve a "scary" new lack of syntax, well ... still, side-by-side
demonstrations like the one in the article are a good way to pique a practical
curiosity.

------
ohyes
'I of course started rambling about how nice it is for concurrent
applications, that you can make a map statement run in multiple threads by
simply changing “map” to “pmap”.'[sic apparent typos]

While this is sort of true, that is not true concurrency, it is parallelism.
It seems that a lot of production Clojure code will end up relying on Java
code at a low level. (That was at least my experience in getting things
performant).

When you do this, it seems to me that you lose some of the safe parallelism
guarantees. Immutable data structures with 'pmap' are great, as long as you
didn't use a mutable Java array somewhere... (This is reasonable, you have
enough rope to hang yourself). The takeaway is not 'instant concurrency', it
simply isn't true. The takeaway 'great built in support for certain types of
concurrency' would be better.

I think the 'fourth' point, Lisp is great at syntax abstraction, has always
been true, and is a great point to make in favor of any lisp. If you know what
you are doing, it is possible to write some extremely pretty, declarative
code. (But again, there's no accounting for taste, and you have enough rope to
hang yourself).

Lisp: enough rope to hang yourself, or write awesome code. Or (more likely) do
both.

------
swannodette
I would honestly answer "It's good at removing complexity from your programs".
People adopted OO because it eliminated certain forms of incidental complexity
from their applications. People adopted GCed languages because it eliminated a
particular serious form of incidental complexity for many applications.

Clojure is good at taking the elements of OO that are sound and ruthlessly
removing the ones that introduce complexity. Especially those problems which
cause incidental complexity to explode under concurrency.

------
grogers
The two examples he gives could be done easily in any programming language
that supports higher order functions (ie. functions which take a function as
an input argument). To a lesser extent he requires lambdas in the with-
memcached example, but it isn't 100% necessary (could have just written the
some-heavy-code part in a named function).

None of this is very novel or unique to clojure. Clojure (and other lisps) do
have some nice syntax sugar to make writing this type of code easily, which is
nice.

------
tsotha
_First of all, the repl is a killer. This is not something that is unique to
clojure, but that doesnt make it less good. Beeing able to try out new api’s
and fumble forward is great._

Spell checker, man!

I don't understand all the REPL love. To me it's great for goofing around with
something you don't understand (like clojure itself, when I started). But
where is the option to save the REPL state? When I'm actually working on a
project it's back to the old edit-compile-run cycle, because otherwise I lose
my work. Granted, the compile is pretty quick, but that's true when I'm
writing java code in eclipse.

~~~
eeperson
How useful the REPL is depends on the language. Some languages have a much
richer REPL related toolset than others. I'm guessing your experience with
REPLs has been with a language such as Python or Ruby which doesn't have a
very rich toolset. I agree that in these languages the REPL is mostly useful
for trying stuff out. However, if you try some thing like Lisp with SLIME then
you will see a very different experience. In SLIME, the REPL lets you interact
with your running application. This lets you query/modify the runtime state.
This, combined with the ability to hot swap your code, gives you nearly
instant feedback for anything you develop.

SLIME gives you some ability to save REPL state in that you can start a REPL
with all of your code already loaded (check out the Clojure bulid tool
Leiningen and the command 'lein swank'). If you want to save the complete
state of a running application you could check out one of the versions of Lisp
with image based persistence or Smalltalk.

~~~
gtani
This has been discussed a fair amount, as well as replaying session
transcripts, persisting key data structures easily, some other things i can't
remember.

[http://groups.google.com/group/clojure/browse_thread/thread/...](http://groups.google.com/group/clojure/browse_thread/thread/6198db7d82610293?hl=en)

[http://groups.google.com/group/clojure/browse_frm/thread/473...](http://groups.google.com/group/clojure/browse_frm/thread/47380010847e2a58#)

[http://stackoverflow.com/questions/3480377/clojure-
namespace...](http://stackoverflow.com/questions/3480377/clojure-namespace-
management-is-there-a-way-to-save-and-restore-the-state-of-cl)

<http://clojure-log.n01se.net/date/2010-01-16.html#i75>

------
lliles
I spent the weekend writing a scraper in Clojure using the HtmlUnit Java
library. As much as possible I aimed for purely functional, side effect free
code, but as with most Java libraries, using the HtmlUnit API forced me to
write functions dealing with mutable, stateful Java objects.

I would have preferred to write everything in a purely functional style
because I agree that it makes testing and reasoning about your code so much
easier. But looking back, the ability to dip into Java (and use the great
HtmlUnit library) was a big win in terms of accomplishing the task at hand.

------
seancron
The main problem I had when I was learning Clojure was definitely finding
good, up-to-date documentation about it. There were many times when I'd try an
example that I had found online, only to find out that something had changed
in Clojure 1.2 since the article was written, or that it wasn't documented
well.

For example: Using command line arguments is not clearly documented. The best
resource that I found was this Stack Overflow answer
[http://stackoverflow.com/questions/1341154/building-a-
clojur...](http://stackoverflow.com/questions/1341154/building-a-clojure-app-
with-a-command-line-interface)

Another problem that I've had with Clojure, is that because programs can be
written so concisely, it's very easy to get lost reading other people's code
when you're first starting out. Things like the "->>" macro and the "#"
shorthand confused me when I was trying to learn Clojure because symbols
aren't very descriptive, and they're very hard to search for.

------
sorenbs
The point about functional languages changing your coding style really is
true. After playing around with lift in a university course i went ahead and
implemented the exact same cache access pattern you have described in a .net
application (using lambda in c#):

var data = Caching.GetOrAdd(cacheKey, () => doWorkAndReturnData);

------
newobj
(time (my-function))

is a pretty horrible example because i can instrument my java code with a
single annotation, which is far less brittle.

~~~
nickik
but you have to use annotation and they suck. :)

------
Tichy
Just skimming the headlines - it sounds as if Clojure is good at Java. That's
it? I hate Java...

Still interested in Clojure, though.

~~~
bobobjorn
Im not saying that it just is good at java. But talking to java developers,
they often ask why they should look at clojure. And for them, i think that
spin makes sense.

