
Getting Started With Clojure - jrheard
http://jrheard.tumblr.com/post/40024238467/getting-started-with-clojure
======
manishsharan
This is a great article. More articles in similar tone are needed to highlight
how simple this language is. A big disservice to Clojure was probably done by
a few early adopters of Clojure who hyped up the LISP heritage of the language
to the extent it turned away C/java guys like myself: I recall reading
somewhere that in order to learn Clojure , one had to master SICP and Scheme.
That was a huge learning curve I did not have time or inclination for.
However, once I waded into Clojure, I was amazed by how simple the language is
really and how productive I could get; Clojure REPL is awesome . I still
haven't mastered the language, I haven't mastered macros, protocols etc. and I
bet my code is ghastly and non-idiomatic but I have still managed to write
Clojure code that does what it is supposed to do in a highly concurrent
workload.

~~~
Sandman
I had the same experience. When I first heard about Clojure, one of the first
things I learned was that it was a Lisp. But having read in numerous comments,
blog posts etc. that "only the top percentile of programmers use Lisp", and
since I don't consider myself to be anywhere near the top percentile, I felt
that my programming chops might not be adequate enough to learn it.

So I put off learning Clojure for about a year or so. However, I grew more and
more weary of Java's obvious shortcomings, the inherent bureaucratic nature of
the language and lack of modern programming features (such was the situation
at the time at least, things are starting to look better for Java nowadays)
and started to look to other languages. I tried Scala. It didn't work out. I
still wanted to leverage my existing knowledge of JVM and the whole Java
ecosystem, so I turned to Clojure again. Also, having spent perhaps too much
time on HN, I really wanted to see what that fuss about Lisp was all about.

Anyway, what I found out was that you do not, in fact, need to be a genius
developer to learn Clojure. Actually, Clojure was everything I hoped for. It's
dead simple. The syntax is minimal compared to some other languages. You may
have heard other people say that learning Lisp can be an enlightening
experience. Yes, there definitely are some enlightening moments, but not in
the sense that you need to spend years meditating on something to be able to
understand it. Read a good book, there are plenty of those around now, watch
some of Hickey's talks, and you'll get it.

To summarize, here's my message to anybody who is thinking of learning Clojure
- don't get discouraged and give up on Clojure before even trying to learn it
just because it's a Lisp. It may seem strange and perhaps a little frightening
at first, but once you spend some time with it, you'll get amazed at how
wonderfully simple it really is, and how powerful it is precisely because of
this simplicity.

~~~
wonderzombie
_since I don't consider myself to be anywhere near the top percentile, I felt
that my programming chops might not be adequate enough to learn it._

See? The magic was within you _all along_.

:)

I wonder if the causation is confused, here. That is, you do not need to be a
top percentile programmer to understand or use Lisp. You are -- or become -- a
top percentile programmer _because_ you've learned Lisp.

I don't know if the relationship is as direct as all that. But I do think that
if you learn and internalize some of the lessons of Lisp, it will expose you
to new ways of thinking about programming as well a programming problems, and
this is correlated with being a good programmer.

One particular example: the close relationship between code and data in Lisp
pulls aside the curtain a bit on some concepts which are more obscured in
languages like Java or C++.

~~~
jwdunne
I don't know about Lisp making me a top-percentile programmer but I do know
learning Lisp has improved my skills (not mastering, of course, but becoming
comfortable reading & writing code in it). I also feel what I've read from
SICP has helped massively too.

For one, recursion. I 'got' it as far as the fact it's a function calling
itself but it was only through digesting Lisp books, writing lisp and talking
about Lisp that I finally got it. SICP helped further with recursive-iterative
stuff too - it doesn't just need to call itself to be recursive.

Another is functional programming.

There are many more but the point is that I could have learned all these
concepts, mentioned or not, in other languages but it was the simplicity of
Lisp that I feel allowed me to truly understand them. I also feel if I
dedicated more time into Lisp, I'd get much more than just a new language out
of it.

------
DigitalJack
I didn't know about clojure-toolbox. That's pretty neat.

One thing though, regarding this page, is that you don't need to install
clojure with brew. Leiningen takes care of all that... clojure is just a jar
that's included in your project, aka a dependency, and Leiningen manages that.
This lets you tie a specific version of clojure to that project, which is
handy for some legacy projects that aren't maintained anymore.

Also, if you drop the brew references, then this becomes OS agnostic. Just go
to the leiningen page on github[1] and it'll get you started: osx, windows,
linux.

I develop with clojure on my mac and I've not brewed anything related to
clojure.

[1] <https://github.com/technomancy/leiningen>

~~~
babs474
This is something that clojure got right before any other language I'm
familiar with did.

You do not "install" clojure. You depend on clojure just like you might log4j
or joda-time

~~~
matthavener
You still need to install the JVM. Python/perl/ruby require installers because
you need some platform-specific stuff for each. Running everything inside the
JVM means you only need to ship what any arbitrary JVM library requires. In
this case, its as simple as a .jar.

~~~
pekk
So Clojure has over (say) Ruby the feature that you don't have to install it.
Yet you do have to install a JVM... How is installing a JVM better than
installing any other interpreter or runtime?

~~~
martinced
_"How is installing a JVM better than installing any other interpreter or
runtime?"_

Maybe, just maybe, the fact that Clojure isn't exactly the only program on
earth running on the JVM and that, hence, there's a probability _p_ far from
zero that the JVM is _already_ installed on your system / on your users'
systems!?

~~~
pekk
There's a good chance that a Perl interpreter is installed on any Linux
system, but this is really an incredibly trivial reason to prefer a language.
If you can't use (say) a ruby installer you are going to have even bigger
problems building almost any kind of software.

------
spacemanaki
> The reason that you won’t find yourself running `clj` often is that the REPL
> built into bare Clojure is pretty much garbage....

This is what rlwrap is for. Call `rlwrap clj` instead of `clj`, and you get
all that and more (C-r, for reverse incremental search, etc). Works with every
other REPL that doesn't bother to re-implement read-line.

~~~
vutekst
Using a raw repl at all is painful compared to just selectively evaluating
expressions from a buffer (say, in Emacs, VimClojure, or the Eclipse and
IntelliJ plugins).

~~~
wonderzombie
I must second this. You _can_ get used to it, and I did. For a while, I used
Vim or ST2 + a terminal window with lein repl.

As of a week or so ago, I started using Emacs with Clojure & nrepl. Aside from
the occasional teething problems (still not used to the Emacs paradigm), it's
amazing. Merely having the REPL in a text-editor-like buffer is a big win, and
there's a bunch more that I'm still incorporating into my workflow.

------
wonderzombie
I knew about clojars.org, but I hadn't known about <http://www.clojure-
toolbox.com/>. Very nice!

I also recommend the Value of Values video presentation:
<http://www.infoq.com/presentations/Value-Values>. It will help you
internalize Clojure's approach to data.

I really wish I could remember why I didn't experience _nearly_ as much pain
starting out as the author, but I'm glad that he took the trouble to put this
together.

~~~
graue
Off topic perhaps, but is Rich Hickey's wisdom _only_ summarized in talks, or
has he written some of this down? I see a number of glowing reviews of videos
like this. While I don't want to miss out, I would personally much rather
consume this info in writing.

The one I did bite the bullet on and watch in full was his talk on “hammock-
driven development”. I liked it, but couldn't help feeling it would have made
a very nice blog post that I could've read in 5 to 10 minutes as opposed to
watching a 30 minute video.

~~~
fogus
While 'Joy of Clojure'[1] can in no way be considered "the way Rich thinks",
we have tried very hard to capture the Clojure philosophy as we understand it.
This is based on personal interactions with Rich, his talks, the Clojure and
Clojure implementations, Datomic, IRC chats and experience using the language
every day.

[1]: <http://www.joyofclojure.com>

------
scarmig
Very nice, JR, best guide I've seen.

I've always wished, though, that all "getting started" guides would just
provide a chef recipe or machine image with everything ready to go. Getting to
know a language shouldn't require jumping through an hour of hoops and
documentation to get it set up.

(Of course, the guide here is broader than simply getting your system set up.)

~~~
michaelsbradley
Thanks to Leiningen[1], getting started with Clojure is super simple.

It doesn't get much easier than pulling down the master `lein` script (or
`lein.bat` for Windows) with wget/curl and setting it up on your PATH as an
executable. This is similar to rvm[2], nvm[3], perlbrew[4], et al.

You'll need to have Java installed before proceeding to the next step.

Once you've done that, you can run `lein repl` in your shell -- Leiningen will
bootstrap itself when it's run for the first time, and when it's done you'll
be presented with a Clojure REPL. Now you're ready to start exploring and
learning:

<http://clojure.github.com/clojure/>

<http://clojuredocs.org/>

<http://clojure-doc.org/>

Also, please join the friendly community in #clojure on irc.freenode.net[5].
You'll find folks in there nearly 24/7 who are willing to answer questions you
may have as you learn your way around. The discussion group[6] is also a great
resource.

[1] <http://leiningen.org/#install>

[2] <https://rvm.io/>

[3] <https://github.com/creationix/nvm>

[4] <http://perlbrew.pl/>

[5] <http://webchat.freenode.net/?channels=clojure>

[6] <http://groups.google.com/group/clojure>

~~~
chc
I wanted to get Clojure on my secondary machine to do a little light fiddling,
but as it turns out, Windows doesn't include wget or curl, and lein.bat
requires those. So I have to download something that requires me to download
something so I can download something that will let me install the thing I
wanted in the first place. I think it could be a bit easier.

~~~
technomancy
It certainly could be better, but none of the maintainers know Windows, and no
Windows users have contributed improvements.

~~~
jurjenh
which makes me wonder if there is a simple java package to do that - probably
not much to write a simple curl / wget for java so that on any machine with a
JVM you can just lein your way to clojure...

~~~
michaelsbradley
I wonder if java.net.HttpURLConnection would be enough?

------
technomancy
I wish people would at least attempt contributing to official documentation
instead of spreading stuff across random blogs.

~~~
jrheard
Fair point, mea culpa :) I'll carve out some time this weekend, figure out how
to make this advice generic across platforms, and figure out how to contribute
it to dev.clojure.org.

~~~
jkkramer
Please do. Good writers like yourself can make a big difference right now.
There's also the Clojure Doc project - <http://clojure-doc.org/>

~~~
jarifikwa
I am a mediocre-at-best Java developer, but somewhat better at writing. I'd
like to learn Clojure and contribute to the community while doing so. Is the
Clojure Doc project the best opportunity for someone like me?

~~~
jkkramer
Clojure Doc is easier since it doesn't require a CA.

IRC (#clojure and #clojure-doc on Freenode) is good for coordinating with
other contributors.

------
leephillips
At first the Clojure environment is confusing: why do I need Leiningen? How do
I use libraries in my project? This article is a good place to start for
beginners, as it explains all that.

------
tesmar2
I have been thinking about getting into Clojure, but time is precious. It
doesn't seem like there are that many jobs out there, but I could be wrong.

For those of you in the industry, why would I want to use Clojure? What would
be a good project to try it on? A Web app? Why is it worth learning it?

~~~
paolovictor
This post is specially relevant for me, since last weekend I've decided to
take a quick look at Clojure, as one of my personal goals this year is to get
acquainted with a Lisp dialect.

From my _very_ short experience (I've started coding a simple game), here are
my two cents:

\- If your application is heavily dependent on state, which changes
continuously and must be maintained during most of the execution time - like a
game - it may not be a good fit. You'll waste a lot of working around the fact
that each modification results on new objects. \- If your application
comprises mainly of short requests that may create some state that will most
certainly be discarded shortly after - like a web application - then I think
it's a good fit and you'll probably enjoy it better.

Once again, I've just got started with it, so take this with a grain of salt
:)

~~~
aphyr
I'd like to contrast this: if your application is heavily dependent on state,
_especially_ state which is shared between threads, Clojure offers a concise,
safe, and uniform way to understand and organize state transformations--at the
cost of performance. Where fast mutability is required, it's easy to drop down
to explicit locks, atomics, java.util.concurrent collections, et al.

I find the majority of my time in writing stateful programs goes towards
reasoning about safety, and having access to STM lets me write correct code
with less thinking. Then I focus on optimizing the parts where performance is
critical.

~~~
billsix
At ILC 2009, Guy Steele asked Rich Hickey how Clojure's STM interacted with
I/O. To which, Rich replied that it doesn't. No further discussion continued
on the subject.

I have found that this rarely enters discussions regarding Clojure, although
the STM is frequently lauded. GHC's STM also does not work with the IOMonad,
which is clear because of the types, and is articulated in books such as such
as Real World Haskell.

[http://book.realworldhaskell.org/read/software-
transactional...](http://book.realworldhaskell.org/read/software-
transactional-memory.html)

Are people really getting benefits from transactions which do not involve I/O?

~~~
jrheard
That's odd, that seems a little inaccurate to me. Clojure's agents are useful
for encapsulating I/O-related resources, and are integrated with the STM
system. Per <http://clojure.org/agents> -

    
    
        Agents are integrated with the STM - any dispatches made in a transaction
        are held until it commits, and are discarded if it is retried or aborted.

~~~
craigching
I'm a clojure newb myself, but I thought STM transactions weren't allowed to
have side-effects and IO would be a side-effect, no?

~~~
jrheard
Refs and atoms shouldn't have side effects, but agents are great for
performing side effects. From page 214 of Clojure Programming:

    
    
        Unlike refs and atoms, it is perfectly safe to use agents to coordinate 
        I/O and perform other blocking operations. This makes them a vital
        piece of any complete application that use refs and Clojure’s STM
        to maintain program state over time. Further, thanks to their semantics,
        agents are often an ideal construct for simplifying asynchronous
        processing involving I/O even if refs are not involved at all.
    

Further:

    
    
        Agents are integrated into Clojure’s STM implementation such that
        actions dispatched using send and send-off from within the scope
        of a transaction will be held in reserve until that transaction
        is successfully committed. This means that, even if a transaction
        retries 100 times, a sent action is only dispatched once, and that
        all of the actions sent during the course of a transaction’s
        runtime will be queued at once after the transaction commits.

------
pandeiro
or,

    
    
      # make sure you have java/open-jdk already
      
      wget https://raw.github.com/technomancy/leiningen/preview/bin/lein && chmod +x lein && ./lein repl

------
dizzystar
I wish someone would do a Learn Clojure the Hard Way. The comments in this
thread is a great documentation of the unfounded fears of the language.

I also want to point out to those who are using Windows: Yeah, you could, but
this is not a good idea. Leiningen 2 is not available for Windows, but you can
still get quite a bit done. At some point, you just have to bite the bullet
and install a VM with Linux to really dive into it.

~~~
DigitalJack
Leiningen 2 is absolutely available on windows. And clojure on windows is the
same as clojure on any other platform. That's the beauty of running on the
JVM.

Light Table has a windows client; Eclipse with the counterclockwise plugin (a
leiningen/clojure plugin) runs great on windows; running from the command
prompt works great on windows.

I agree though, that a "Learn Clojure The Hard Way" a la Shaw would be nice.

~~~
dizzystar
Really? The only thing I get when I attempt to install Lein2 on Windows is
"This is not available on Windows." Running Windows 7 Home.

I'm not a huge fan of using a bunch of IDEs and just use Emacs. After a year
of fighting with Windows, I got fed up with it and installed Linux with a VM
and now everything works like a dream.

EDIT TO ADD: I would love to do a project like Learn Clojure the Hard Way, but
I'm simply not confident in my abilities to do it correctly. I've written some
pretty significant programs in Clojure (see my profile), but I wouldn't be
able to solve but a few Project Eulers with it. I'm simply too new at
programming in general.

~~~
DigitalJack
I'm a Mac person myself, but use windows for work and have leiningen and
clojure running fine.

I just used the batch file from the leiningen github to get up and running on
windows.

Someone else brought up the point that lein needs wget or curl, and that isn't
something that is installed by default on windows. I happened to already have
them, so I never thought much about it.

GNU has a version of wget and maybe curl too for win32. And there is always
cygwin if you like.

<https://github.com/technomancy/leiningen>
<http://gnuwin32.sourceforge.net/packages/wget.htm>

------
tripzilch
Shouldn't the title say "Getting Started With Clojure in OSX"?

------
gits1225
"When I was going through all this myself a few months back, there was a weird
period of a good few weeks when I had basically no mental map of the Clojure
ecosystem and had no idea how to assemble one."

One of the things you can do when learning something new is to hop onto IRC
and join a channel related to the topic. I almost always have got a good
overview of things just by asking around what I am supposed to know.

------
paddyoloughlin
I'm interested in learning LISP. How good a choice is learning Clojure as a
way of achieving this?

I've read a page[1] listing differences between Clojure and other LISPs, but
I'm not sure that I fully understand the implications of these differences.

[1] <http://clojure.org/lisps>

~~~
jrheard
Clojure's a great lisp. I recommend it highly. I haven't spent much time with
Scheme, but I can definitely say that I greatly prefer Clojure to Common Lisp.

------
jumanjisama
<http://youtu.be/VVd4ow-ZcX0>

this video by Chas Emerick (co-author of clojure programming) also gives a
good introduction to start with clojure, especially for people who uses
eclipse.

------
politician
I hope the Light Table guys see this article and incorporate the guide into
their OOBE content. hint, hint ;)

------
147
Anybody have any ideas for beginner projects in Clojure?

~~~
khill
Not necessarily a project but a good way to learn is using 4clojure:

<http://www.4clojure.com/>

------
dschiptsov
The same thing could be done in Python (with requests) and Ruby (with
whatever-it-is) with more clarity, less confusion, and _much_ less consumption
of resources.)

    
    
      (:headers resp)
    

This construction is confusing - it breaks environmental model (scoping) _and_
general evaluation rule of Lisps - is :headers a global symbol? a part of foo
namespace? Is it macros?

    
    
      (resp :headers)
    

On the other hand, this form is perfectly consistent - I'm sending to some
closure which is bound in a global or other environment a constant message.

The assumption that the reader function implicitly transforms first form to
second is of no good, because it is not obvious and breaks intuition about
environments and violates principle of less astonishment.

That thing (:headers resp) returned - what language is it?)

~~~
wtetzner
>This construction is confusing - it breaks environmental model (scoping) and
general evaluation rule - is :headers a global symbol? a part of foo
namespace? Is it macros?

It follows Clojure's evaluation rules just fine: it's an object that
implements the IFn interface.

> On the other hand, this form is perfectly consistent - I'm sending to some
> closure which is bound in a global or other environment a constant message.

resp isn't a closure, it's a map, which is also an object that implements IFn.

~~~
dschiptsov
How could you tell this from the code?)

~~~
prospero
Because keywords are functions which are implemented such that:

    
    
        (:keyword m)
    

calls in turn

    
    
        (get m :keyword)
    

That's just a basic feature of the language. No macros involved.

~~~
dschiptsov
So, reader knows about keywords and does this implicit syntactic
transformation?

It seems to me that a _function_ must be defined somewhere before one could
call it.)

~~~
mjw
The keyword syntax is transformed into a keyword instance by the reader, and
keyword instances implement IFn as objects on the JVM, hence can be used as
functions under clojure's evaluation rules.

As I understand it, the roles which things like lists and functions play in a
traditional lisp are replaced in Clojure by abstract datatypes corresponding
to Java interfaces. Which on one hand is kinda neat because the core lisp
datatypes aren't tied to specific concrete implementations and other datatypes
(including user-defined ones) can participate in the same abstractions.

On the other hand it means the semantics become quite tied up in underlying
JVM-related details and don't seem as clean/elegant as (say) Scheme.

~~~
fogus

        On the other hand it means the semantics 
        become quite tied up in underlying JVM-related 
        details and don't seem as clean/elegant as (say) 
        Scheme.
    

That's not very true. Instead, Clojure is defined in terms of specific
abstractions. Whether those take the form of interfaces or protocols is
irrelevant because it's the abstractions that count. If it were tied strictly
to JVM-related details then ClojureScript would have been much harder to
implement than it was.

The elegance of Scheme is subjective.

~~~
mjw
You have to use the java interop facilities if you want your own types to
implement these abstractions though right?

I recall some debate about changing this so you can implement them using the
native abstraction facilities in clojure (protocols), at which point I'd
probably withdraw my point.

But yeah elegance is subjective. I use Clojure and broadly like it, JVM
interop is really useful, but the lack of a crisp separation between clojure
semantics and JVM semantics does still irk the purist in me a bit.

I guess I'd see Clojure and ClojureScript not as one language on two host
platforms, but as one JVM language and another similar but not really source-
compatible language on another platform which is influenced by it. Part of the
philosophy seems to be to make pragmatic decisions which blur the boundary
with the host platform, rather than try to abstract over the differences in
APIs and runtime semantics.

~~~
craigching
I'm still a clojure newb, but if I understand you correctly:

>> I recall some debate about changing this so you can implement them using
the native abstraction facilities in clojure (protocols)

You mean records (defrecord): <http://clojure.org/datatypes>

~~~
mjw
Not quite, I'm talking about replacing the various important java interfaces
in clojure.lang (IFn, ISeq, IPersistentMap etc) with protocols, so you can
implement them yourself without using any Java-specific language features.

Dunno how feasible this is, but if a language is going to define its own
abstraction features (here, protocols) on top of the underlying platform, it
would seem cleaner to eat ones own dogfood in using these abstraction
facilities for the core abstractions which the language and its core library
are based on.

