Clojure from the ground up: welcome

This guide aims to introduce newcomers and experienced programmers alike to the beauty of functional programming, starting with the simplest building blocks of software. You’ll need a computer, basic proficiency in the command line, a text editor, and an internet connection. By the end of this series, you’ll have a thorough command of the Clojure programming language.

Who is this guide for?

Science, technology, engineering, and mathematics are deeply rewarding fields, yet few women enter STEM as a career path. Still more are discouraged by a culture which repeatedly asserts that women lack the analytic aptitude for writing software, that they are not driven enough to be successful scientists, that it’s not cool to pursue a passion for structural engineering. Those few with the talent, encouragement, and persistence to break in to science and tech are discouraged by persistent sexism in practice: the old boy’s club of tenure, being passed over for promotions, isolation from peers, and flat-out assault. This landscape sucks. I want to help change it.

Women Who Code, PyLadies, Black Girls Code, RailsBridge, Girls Who Code, Girl Develop It, and Lambda Ladies are just a few of the fantastic groups helping women enter and thrive in software. I wholeheartedly support these efforts.

In addition, I want to help in my little corner of the technical community–functional programming and distributed systems–by making high-quality educational resources available for free. The Jepsen series has been, in part, an effort to share my enthusiasm for distributed systems with beginners of all stripes–but especially for women, LGBT folks, and people of color.

As technical authors, we often assume that our readers are white, that our readers are straight, that our readers are traditionally male. This is the invisible default in US culture, and it’s especially true in tech. People continue to assume on the basis of my software and writing that I’m straight, because well hey, it’s a statistically reasonable assumption.

But I’m not straight. I get called faggot, cocksucker, and sinner. People say they’ll pray for me. When I walk hand-in-hand with my boyfriend, people roll down their car windows and stare. They threaten to beat me up or kill me. Every day I’m aware that I’m the only gay person some people know, and that I can show that not all gay people are effeminate, or hypermasculine, or ditzy, or obsessed with image. That you can be a manicurist or a mathematician or both. Being different, being a stranger in your culture, comes with all kinds of challenges. I can’t speak to everyone’s experience, but I can take a pretty good guess.

At the same time, in the technical community I’ve found overwhelming warmth and support, from people of all stripes. My peers stand up for me every day, and I’m so thankful–especially you straight dudes–for understanding a bit of what it’s like to be different. I want to extend that same understanding, that same empathy, to people unlike myself. Moreover, I want to reassure everyone that though they may feel different, they do have a place in this community.

So before we begin, I want to reinforce that you can program, that you can do math, that you can design car suspensions and fire suppression systems and spacecraft control software and distributed databases, regardless of what your classmates and media and even fellow engineers think. You don’t have to be white, you don’t have to be straight, you don’t have to be a man. You can grow up never having touched a computer and still become a skilled programmer. Yeah, it’s harder–and yeah, people will give you shit, but that’s not your fault and has nothing to do with your ability or your right to do what you love. All it takes to be a good engineer, scientist, or mathematician is your curiosity, your passion, the right teaching material, and putting in the hours.

There’s nothing in this guide that’s just for lesbian grandmas or just for mixed-race kids; bros, you’re welcome here too. There’s nothing dumbed down. We’re gonna go as deep into the ideas of programming as I know how to go, and we’re gonna do it with everyone on board.

No matter who you are or who people think you are, this guide is for you.

Why Clojure?

This book is about how to program. We’ll be learning in Clojure, which is a modern dialect of a very old family of computer languages, called Lisp. You’ll find that many of this book’s ideas will translate readily to other languages; though they may be expressed in different ways.

We’re going to explore the nature of syntax, metalanguages, values, references, mutation, control flow, and concurrency. Many languages leave these ideas implicit in the language construction, or don’t have a concept of metalanguages or concurrency at all. Clojure makes these ideas explicit, first-class language constructs.

At the same time, we’re going to defer or omit any serious discussion of static type analysis, hardware, and performance. This is not to say that these ideas aren’t important; just that they don’t fit well within this particular narrative arc. For a deep exploration of type theory I recommend a study in Haskell, and for a better understanding of underlying hardware, learning C and an assembly language will undoubtedly help.

In more general terms, Clojure is a well-rounded language. It offers broad library support and runs on multiple operating systems. Clojure performance is not terrific, but is orders of magnitude faster than Ruby, Python, or Javascript. Unlike some faster languages, Clojure emphasizes safety in its type system and approach to parallelism, making it easier to write correct multithreaded programs. Clojure is concise, requiring very little code to express complex operations. It offers a REPL and dynamic type system: ideal for beginners to experiment with, and well-suited for manipulating complex data structures. A consistently designed standard library and full-featured set of core datatypes rounds out the Clojure toolbox.

Finally, there are some drawbacks. As a compiled language, Clojure is much slower to start than a scripting language; this makes it unsuitable for writing small scripts for interactive use. Clojure is also not well-suited for high-performance numeric operations. Though it is possible, you have to jump through hoops to achieve performance comparable with Java. I’ll do my best to call out these constraints and shortcomings as we proceed through the text.

With that context out of the way, let’s get started by installing Clojure!

Getting set up

First, you’ll need a Java Virtual Machine, or JVM, and its associated development tools, called the JDK. This is the software which runs a Clojure program. If you’re on Windows, install Oracle JDK 1.7. If you’re on OS X or Linux, you may already have a JDK installed. In a terminal, try:

which javac

If you see something like


Then you’re good to go. If you don’t see any output from that command, install the appropriate Oracle JDK 1.7 for your operating system, or whatever JDK your package manager has available.

When you have a JDK, you’ll need Leiningen, the Clojure build tool. If you’re on a Linux or OS X computer, the instructions below should get you going right away. If you’re on Windows, see the Leiningen page for an installer. If you get stuck, you might want to start with a primer on command line basics.

mkdir -p ~/bin cd ~/bin curl -O chmod a+x lein

Leiningen automatically handles installing Clojure, finding libraries from the internet, and building and running your programs. We’ll create a new Leiningen project to play around in:

cd lein new scratch

This creates a new directory in your homedir, called scratch. If you see command not found instead, it means the directory ~/bin isn’t registered with your terminal as a place to search for programs. To fix this, add the line

export PATH="$PATH":~/bin

to the file .bash_profile in your home directory, then run source ~/.bash_profile. Re-running lein new scratch should work.

Let’s enter that directory, and start using Clojure itself:

cd scratch lein repl

The structure of programs

When you type lein repl at the terminal, you’ll see something like this:

aphyr@waterhouse:~/scratch$ lein repl nREPL server started on port 45413 REPL-y 0.2.0 Clojure 1.5.1 Docs: (doc function-name-here) (find-doc "part-of-name-here") Source: (source function-name-here) Javadoc: (javadoc java-object-or-class-here) Exit: Control+D or (exit) or (quit) user=>

This is an interactive Clojure environment called a REPL, for “Read, Evaluate, Print Loop”. It’s going to read a program we enter, run that program, and print the results. REPLs give you quick feedback, so they’re a great way to explore a program interactively, run tests, and prototype new ideas.

Let’s write a simple program. The simplest, in fact. Type “nil”, and hit enter.

user=> nil nil

nil is the most basic value in Clojure. It represents emptiness, nothing-doing, not-a-thing. The absence of information.

user=> true true user=> false false

true and false are a pair of special values called Booleans. They mean exactly what you think: whether a statement is true or false. true, false, and nil form the three poles of the Lisp logical system.

user=> 0 0

This is the number zero. Its numeric friends are 1, -47, 1.2e-4, 1/3, and so on. We might also talk about strings, which are chunks of text surrounded by double quotes:

user=> "hi there!" "hi there!"

nil, true, 0, and "hi there!" are all different types of values; the nouns of programming. Just as one could say “House.” in English, we can write a program like "hello, world" and it evaluates to itself: the string "hello world". But most sentences aren’t just about stating the existence of a thing; they involve action. We need verbs.

user=> inc #<core$inc clojure.core$inc@6f7ef41c>

This is a verb called inc–short for “increment”. Specifically, inc is a symbol which points to a verb: #<core$inc clojure.core$inc@6f7ef41c>– just like the word “run” is a name for the concept of running.

There’s a key distinction here–that a signifier, a reference, a label, is not the same as the signified, the referent, the concept itself. If you write the word “run” on paper, the ink means nothing by itself. It’s just a symbol. But in the mind of a reader, that symbol takes on meaning; the idea of running.

Unlike the number 0, or the string “hi”, symbols are references to other values. when Clojure evaluates a symbol, it looks up that symbol’s meaning. Look up inc, and you get #<core$inc clojure.core$inc@6f7ef41c>.

Can we refer to the symbol itself, without looking up its meaning?

user=> 'inc inc

Yes. The single quote ' escapes a sentence. In programming languages, we call sentences expressions or statements. A quote says “Rather than evaluating this expression’s text, simply return the text itself, unchanged.” Quote a symbol, get a symbol. Quote a number, get a number. Quote anything, and get it back exactly as it came in.

user=> '123 123 user=> '"foo" "foo" user=> '(1 2 3) (1 2 3)

A new kind of value, surrounded by parentheses: the list. LISP originally stood for LISt Processing, and lists are still at the core of the language. In fact, they form the most basic way to compose expressions, or sentences. A list is a single expression which has multiple parts. For instance, this list contains three elements: the numbers 1, 2, and 3. Lists can contain anything: numbers, strings, even other lists:

user=> '(nil "hi") (nil "hi")

A list containing two elements: the number 1, and a second list. That list contains two elements: the number 2, and another list. That list contains two elements: 3, and an empty list.

user=> '(1 (2 (3 ()))) (1 (2 (3 ())))

You could think of this structure as a tree–which is a provocative idea, because languages are like trees too: sentences are comprised of clauses, which can be nested, and each clause may have subjects modified by adjectives, and verbs modified by adverbs, and so on. “Lindsay, my best friend, took the dog which we found together at the pound on fourth street, for a walk with her mother Michelle.”

Took Lindsay my best friend the dog which we found together at the pound on fourth street for a walk with her mother Michelle

But let’s try something simpler. Something we know how to talk about. “Increment the number zero.” As a tree:

Increment the number zero

We have a symbol for incrementing, and we know how to write the number zero. Let’s combine them in a list:

clj=> '(inc 0) (inc 0)

A basic sentence. Remember, since it’s quoted, we’re talking about the tree, the text, the expression, by itself. Absent interpretation. If we remove the single-quote, Clojure will interpret the expression:

user=> (inc 0) 1

Incrementing zero yields one. And if we wanted to increment that value?

Increment increment the number zerouser=> (inc (inc 0)) 2

A sentence in Lisp is a list. It starts with a verb, and is followed by zero or more objects for that verb to act on. Each part of the list can itself be another list, in which case that nested list is evaluated first, just like a nested clause in a sentence. When we type

(inc (inc 0))

Clojure first looks up the meanings for the symbols in the code:

(#<core$inc clojure.core$inc@6f7ef41c> (#<core$inc clojure.core$inc@6f7ef41c> 0))

Then evaluates the innermost list (inc 0), which becomes the number 1:

(#<core$inc clojure.core$inc@6f7ef41c> 1)

Finally, it evaluates the outer list, incrementing the number 1:


Every list starts with a verb. Parts of a list are evaluated from left to right. Innermost lists are evaluated before outer lists.

(+ 1 (- 5 2) (+ 3 4)) (+ 1 3 (+ 3 4)) (+ 1 3 7) 11

That’s it.

The entire grammar of Lisp: the structure for every expression in the language. We transform expressions by substituting meanings for symbols, and obtain some result. This is the core of the Lambda Calculus, and it is the theoretical basis for almost all computer languages. Ruby, Javascript, C, Haskell; all languages express the text of their programs in different ways, but internally all construct a tree of expressions. Lisp simply makes it explicit.


We started by learning a few basic nouns: numbers like 5, strings like "cat", and symbols like inc and +. We saw how quoting makes the difference between an expression itself and the thing it evaluates to. We discovered symbols as names for other values, just like how words represent concepts in any other language. Finally, we combined lists to make trees, and used those trees to represent a program.

With these basic elements of syntax in place, it’s time to expand our vocabulary with new verbs and nouns; learning to represent more complex values and transform them in different ways.

Vasudev Ram
Vasudev Ram, on

Nice idea, Kyle.

svankie, on

Loving this.

david karapetyan
david karapetyan, on

Looking forward to what’s next.


Seriously? LISP? Haven’t we learned?

Peter, on

Seriously? LISP? Haven’t we learned?

Apparently you haven’t


Seriously? LISP? Haven’t we learned?

Apparently you haven’t


Johnny Chang
Johnny Chang, on

Awesome! Eagerly awaiting the next installment!

alex, on

I have to make a comment entirely unrelated to your post - I love your blog design and layout. It is great. The comments, the terminal CSS, etc. great job.


I’m definitely following these posts.

Thank you! :)

ScientificCoder, on

Nice ! I’ll be sure to point newcomers to your site. Kuddos and keep them coming ! ☺


Aahz, on

It’s not really clear who this is aimed at. For example, I got here through a feed thingie (DuckDuckGo on Android) and had no idea what exactly Clojure was until I saw the magic word “LISP”. Might be a good idea to at least link to something.

Rick James
Rick James, on

The whole white knight paragraph was horrible. Nobody thinks you’re a great guy because you did that. You’re just an asshole.

Kasim, on


Great post and keep up the good work. I’d be happy to help with reviewing codes and such before you publish.

Just let you know we are hiring Clojure developers. Come check us out:

Jbeja, on

Loving this and thanks for the encouraging intro ( i am gay), just reading the “Clojure data analisys cookbook” and this will help me to go trough the chapters.

Mark Wotton
Mark Wotton, on

Nice tute - but isn’t it a read-Eval-print-loop, not execute?

epyf, on

Well, women, LGBT and people of color can always take classes on Coursera. The quality there is high too, and they won’t get the impression of being “people with special teaching ”. Or flagships - want it or not.

I do understand that the tutorial is aimed at just anybody, but this is really the feeling I get when I read that paragraph (but I’m white and straight, that may be the reason)

epyf, on

Well, women, LGBT and people of color can always take classes on Coursera. The quality there is high too, and they won’t get the impression of being “people with special teaching ”. Or flagships - want it or not.

I do understand that the tutorial is aimed at just anybody, but this is really the feeling I get when I read that paragraph (but I’m white and straight, that may be the reason)


user=> ‘(1 (2 (3 ())) (1 (2 (3)))

is this a mistake?

Andreas, on

Hi Kyle,

the goals of this introduction you’re mentioning are just wonderful. I have nothing than deep respect for your openness, encouragement and your profound technical skills! Please, just keep walking this path.

Best, Andreas

jarppe, on

Hello Kyle,

I really liked you approach where you introduce quoting first, then using quoting introduce a list, and only then calling functions.

I have been giving Clojure introductions and I usually start from literals and simple collections. When I go from vectors to lists I have to introduce quoting and evaluation at the same time and this is usually hard to grasp.

Next I will try to introduce Clojure to my 18 years old daughter and I think I’ll use your blog as starting point. So please continue your excellent blog.

Br, Jarppe

Aphyr, on

Good catch, it is a mistake. Thanks M.

Aphyr, on

I agree, jarppe. Went back and forth several times on whether it made more sense to introduce the (fun & args) syntax initially–and introduce the concept of evaluation as substitution–or stick with more concrete semantics as in Chapter 2. I… think it paid off; folks seem to be following this path without getting too lost, and it sets the stage for a deeper exploration of substitution later.

Definitely a more abstract path, though. I’m trying to explain the core structure as deeply as possible without getting bogged down, but without losing sight of inductive learners either. We’ll see how it goes. :)

Sergey, on

Hello, Kyle! You are a man! Thanks a bunch for this guide, looking forward to next posts :)

Adrian, on

Thankyou for this article. I often find myself wallpapering over my sexuality in professional environments to avoid any “awkward looks”. It is important for queer coders to be visible to their peers and their lives celebrated equally. It put a smile on my face to read something that speaks to me both socially and technically :)

LitoNico, on

Thanks for both the article and statement of purpose! This is a great reference for learning clojure– especially since I’m completely new to lisps.

Juan Manuel
Juan Manuel, on

Why don’t you publish this as a book? The contents deserve it.

Marko Bonaci
Marko Bonaci, on

I love you dude. And I’m strait! :)

Ahsen, on

nice tutorial, eagerly waiting for the next chapters.


This is wonderful. Thank you.

Mathew Bentley
Mathew Bentley, on

So happy to read this guide. You are an absolute programming badass, thanks for sharing some of that with the rest of us!

Aphyr, on

Thanks for the kind words, all. Goal has always been to produce a full-length book; hopefully some time by the end of the year.

Rob, on

Just to counterbalance the opening slightly, and perhaps this is just an encouraging view of the way things are where I live, but certainly at my software company we’ve interviewed female applicants whose CVs weren’t good enough, but we wanted to hire more women. One colleague hired this way didn’t know the difference between megabytes and gigabytes, but the point is it certainly wasn’t an environment that discouraged female hires.

When I was at school and university white guys such as myself weren’t encouraged socially to keep doing tech/geeky studies; in fact one chief idea is that women don’t like guys who do that sort of thing. I think facing opposition is something we all do if we want to do something that isn’t socially normal, and it’s hard (but necessary) to try and not confuse that opposition that almost everyone faces with some genuine victimisation that one has felt in the past, or lump all opposition together as having the same cause. E.g. if you have two guys who don’t like you, one of them might not because of your gender or sexuality or whatever (i.e. unfair victimisation) and the other might not because he doesn’t feel you work hard enough. If that happens, don’t think that both guys don’t like your for the victimisation reason, easy though it is to do.

I’m a Brit working in South Africa, and Afrikaaners sometimes give me a hard time. I keep smiling and chatting nicely, and eventually they stop thinking of me as British and just think of me as a person. I haven’t yet written a technical blog post that starts by encouraging Brits to work in South Africa :)

Amy Jenkins
Amy Jenkins, on

One of the most useful things for a beginner to do is to muck around with the command line. Thanks for this!

Lee Spector
Lee Spector, on

I really like this series of posts and I’m considering recommending it to my students in a Clojure-based AI course in the fall. Is there a table of contents page that I’ve missed? Easy to create externally, of course, but it’d be nice to have one on the site if there isn’t one already. FWIW I created something that uses an approach that’s similar in some ways (clojinc, at github/lspector), but whereas I provided almost no text at all between code snippets, you’ve provided lots and lots of helpful text. Thanks!

anonymous, on

Is there a table of contents page that I’ve missed?

Right up top, at the tags list: I’ll be reformatting all this work for the book, eventually, where there’ll be actual chapter headings, etc. Had a bunch of other stuff on my plate recently but starting to get back to writing on CFTGU this month. :)

Mike, on

Thanks for making this series! I’m a novice trying to learn distributed systems and clojure, this blog is awesome. Two quick suggestions for the getting started section:

Ii’m on Ubuntu 14.04 and this works for me which javacc

curl -O

Sam, on


I’m new to Clojure. I was considering implementing data structures like BST etc in this and thought having a namespace clojure.tree might be a good idea. But others felt it was a horrible idea as there were other data structures that does all this work. Could you explain more about those?


Peter, on

Was going to use this resource until I saw the psychotic rants of the author. No way I would support someone with such hatred for other people. get over it - most coders are male, most people are straight. No reason to become a hate-monger.

Kevin, on

I agree with Rob. The beginning of this blog post is a bit too much and needs some counterbalancing. Honestly, I think your post would be much better without it. Perhaps you could just add a link to your rant? And put a disclaimer saying, “This is for everyone and here is why .” In my opinion rants like this are why people think of others so differently. As a child I never really noticed/thought about someone else being different. I always just saw them as a person without paying any attention to these differences I had yet to learn about. As I grew older I read rants like this one, and listened in history classes, etc. Eventually you are taught to think people are different. It is not that teachers or people around you meant to teach you to think that way, but just the mere discussion of differences implants those thoughts at least subconsciously into the brain. If I had never had anyone tell me the word racism or try to explain differences, I would not know what those concepts were in the first place. I am not saying that history is unimportant, but that if conversations like this were less… Perhaps children would not repeat the same mistakes. Perhaps children would not see these differences that were taught to me. Perhaps children will be able to read the actual content of a blog post instead of a long rant about equality followed by the content they visited the blog post for in the first place.

Sam, on

Thanks for this. You write well and the technical pace is perfect and easy to follow.

kiquetal, on

When will the book be available on github?. I love learning xD

Eugene Goostman
Eugene Goostman, on

Very sad to see that you do not include very clever AI chatterbots as well. Alas, I must search elsewhere to learn Clojure

Dave Cottlehuber
Dave Cottlehuber, on

Thanks for one of the clearest introductions resources for Clojure, and the Jepsen series are an excellent gateway drug to the diabolic and fascinating world of distributed systems.

Weslley, on

Hi, this introduction saved my life in starting to learn Clojure. Congratulations for your effort! Thanks

Max G. Faraday
Max G. Faraday, on

Hey, Love this… Great, Exceptional body of work you have here. I am sure I am not the only one with this sentiment: THANK YOU. I have been coding for 24 years now and in Clojure for the last few. Thanks, really good job.

Sed, on

“People of color” Seriously, dude. Suck my dick.

Benjohn, on

Hi Aphyr, nice work.

I like you take on introducing quoted symbols before introducing executing them. I think it works too, and it’s definitely not something I’ve seen before. I’m learning Clojure myself (as a long term programmer), but I think this walk through would also work for my son (8), and when they’re a bit older, his siblings. I like how it starts them at the command line, talks them through checking their tool versions, installing, etc. Nice.

I also like your intro. There are a many Clojure guides – but this one is yours. You introduce it how the hell you like! I don’t think you need me to tell you that :-) But other readers, maybe they do.

It’s stuff that still, sadly, needs saying. Not, I think, because people are necessarily bigoted, but because people just don’t appreciate how it is to live the life of others around them. It’s good to be reminded.

Jack, on

Hy can’t I read something these days without touthing the LGBT shit? IT industry is sick.

Jack, on

Despite the LGBT syndrome, the article series is simply the best.

JSteve, on

I wanted to read this article, but the several paragraphs of political BS at the beginning completely turned me off. Yes, I’m a white straight male. No, I don’t have a problem with you (or anyone else) being different. Why don’t you stop worrying about it so much and just focus on the tech? It really has no place in this type of article.

You’re white and male and you spent a lot of time representing females and minorities, which to me makes it sound like YOU consider them second class citizens who are unable to represent themselves. Get off the high horse and write something that doesn’t make me want to barf. I don’t hate you or people like you, but I do hate all this victimization crap.

Shayne O
Shayne O, on

Good work on reaching out to women and other less represented groups. Having youngsters in my family interested in coding, a lot of the attitudes seems discouraging for the girls, so I think its great folks are making an effort to reach out.

Never mind the huffing and puffing troglodytes who weaze and moan everytime someone even suggests including folks often excluded in this industry, they are on the wrong side of history and they know it. Your doing the right thing Kyle. :)

Terrence Brannon
Terrence Brannon, on

Without this guide, where would one start with Clojure? I dont know and I dont want to entertain the thought.

That being said, you do not need Leinengen to start with clojure. I was behind a corporate firewall teach myself clojure and could not access things like lein through the proxy.

You can just download clojure. And optionally download clojure-mode and inf-clojure from github and away you go!

vikram, on

It is a very good one can you publish this one as a book?

Daniel Carpenter
Daniel Carpenter, on

Thank you so much for this. What a wonderful resource.

Patrick, on

Thank you for writing this guide, and for your introduction. Both are awesome.

rosazon, on

“Who is this guide for?” seriously dude, this does not belong in a technical guide. It doesn’t matter if you’re not straight or whether you’re writing for women or “people of color”. I want to learn Clojure but if you’re going to put all your emphasis on minorities (like me, mind you), then I would rather learn from someone who actually cares about teaching. You should be ashamed.

Maia, on

Ooooph, some of the comments here. :-\ I thought your intro was welcoming and personal, and I appreciated it. So far this guide is really helpful and clear, and the order is making more sense to me than other Clojure tutorials I’ve been looking at. Thank you for writing it!

cig0, on

If you like to avoid as much as possible to clutter your base system with cruft, there’s an official Clojure Docker container ready to rock with everything you might need:

Post a Comment

Please avoid writing anything here unless you are a computer: This is also a trap:

Supports github-flavored markdown for [links](, *emphasis*, _underline_, `code`, and > blockquotes. Use ```clj on its own line to start a Clojure code block, and ``` to end the block.

Copyright © 2017 Kyle Kingsbury.
Non-commercial re-use with attribution encouraged; all other rights reserved.
Comments are the property of respective posters.