

A Clojure Crash Course - nonrecursive
http://www.braveclojure.com/do-things/

======
brudgers
Concludes with:

 _By this point I highly recommend actually writing some code to solidify your
Clojure knowledge if you haven 't started already._

While I will be among the quickest to acknowledge that there is great value to
be gained by typing in example code, without structured exercises, the article
might be providing a fine tutorial or feature list or cookbook, but it is not
a course.

Courses look more like "Learn Python the Hard Way" than blog entries. They're
hard to make and one for Clojure is sorely needed. The easy parts of Clojure
are the syntax and the common idioms. That's why Lisps have a long history as
introductory programming languages. The hard part is learning to apply them to
the sort of hard problems that one applies other programming languages to.

All that to say, that there's nothing wrong with the article as an article. In
fact I think it represents an admirable amount of work for a positive purpose.
My only criticism is that it is not what it says it is, and the only reason
that is a criticism is that it claims to do heavy lifting which it does not.

~~~
nonrecursive
Apologies if the title submitted to HN was confusing. The actual chapter title
is "Do Things: a Clojure Language Crash Course" but I felt that was too
verbose here. The text is explicit about what will be covered: "In this
chapter, you're going to explore the elements which comprise this Lisp core:
syntax, functions, and data."

Clojure _language_ crash course is meant to distinguish these aspects from the
other aspects of Clojure: the environment, the artifact ecosystem, and the
mindset. I mention this distinction in the introduction:
[http://www.braveclojure.com/](http://www.braveclojure.com/)

Other chapters begin to cover the mindset, or how to do things the Clojure
way. "The Joy of Clojure" also covers this, from what I understand. Rich
Hickey's talks are also great, of course.

~~~
brudgers
I agree. Rich Hickey's talks are an excellent resource, and he refers to them
as talks not as courses, even though he expects and hopes some people will
learn something from them.

There's nothing to apologize for. It's just that it isn't a crash course, or a
course of any kind for any meaningful meaning of "course".

And I meant what I said about the amount of effort and thought that the
article represents being worthy of praise...and what I said about there being
a need for actual courses in Clojure.

~~~
Goladus
>It's just that it isn't a crash course, or a course of any kind for any
meaningful meaning of "course".

It absolutely is a crash course, for the most common colloquial definition of
the term "crash course," although in a very nitpicky fashion the blog entry is
not a "true course of study." The reality is when people say "crash course" in
common English they almost never mean a formal course of study. Usually it's
used in the context of someone needing to learn something quickly in order to
do something else. A professor might spend 10 minutes at the beginning of a
class doing a "crash course" on binary arithmetic, because it's needed for
something else that's on the lesson plan for the day. Such a crash course
might have no exercises and no materials whatsoever, but nobody reasonable is
going to object to the term.

The blog entry is focused, brisk, and thorough, the key elements of a course
intended to be completed rapidly for a specific purpose. Does it fail to fill
a learning gap that clojure needs filled? Probably. But that doesn't make it
wrong to call it a crash course.

~~~
brudgers
Typically a crash course is equal in content and student expectations to a
normal course. What makes it a crash course is that it has a compressed time
schedule. Courses with an emphasis on lightening the weight of the content
typically are prefixed by "A Survey of", "An Introduction to", etc.

The professor covering binary arithmetic does not hear objections for several
reasons. While the social context of the classroom and the explicit expert-
novice relationship are among them, the analogy is undermined because teaching
Clojure is not a precursor to teaching something else. In the article it is
the end, itself.

Under the usage you are suggesting, "A crash course in the JVM" in the context
of teaching Clojure would fit the analogy better.

~~~
girvo
Honestly, no, you're incorrect, at least in Australian English. A crash course
is a turn of phrase, to denote being taught an overview of a topic in a short
time, usually informally, with a focus on what is important to the students
future endeavours in that area.

------
mjburgess
There really needs to be a JVM crash-course for clojure... I can understand
the syntax well-enough, but I want to know what java libs i need/how i use
them/etc. ie. when I have to "leave clojure".

~~~
grayrest
[http://www.clojure-toolbox.com/](http://www.clojure-toolbox.com/)

Clojure has been around long enough that people have wrappers around most of
the interesting common use java libs. If you're looking for something domain
specific then it's usually better to find which java libs cover the domain and
work from there.

~~~
DigitalJack
On top of that, direct java interop is not bad at all.

Here is a talk on it: [http://www.infoq.com/presentations/Clojure-Java-
Interop](http://www.infoq.com/presentations/Clojure-Java-Interop)

I confess I haven't watched that talk yet and only remembered hearing about it
as I wrote this. But I imagine it is a good Launchpad.

~~~
andrewflnr
The point is, direct Java interop is useless, potentially worse, if you don't
know anything about Java.

------
nonrecursive
I hope this provides a good introduction to the Clojure language, apart from
concerns about building and running Clojure programs. I'd love any feedback :)

~~~
jdludlow
I can't speak to the Clojure introduction, because I was already semi-familiar
with the language. However, I found your site via Google a few weeks ago when
I was looking for an introduction to Emacs + Clojure. Having gone down this
road several times in the past, I have to say that this is the best tutorial
I've ever found on that topic.

The repl and window examples were just what I needed as a complete Emacs
newbie. The Emacs chapter was similarly good. It seemed to be aimed at someone
who wanted to start writing code quickly. This is the first time in years that
I've worked through an Emacs tutorial without firing up vim to edit a config
file (at which point I usually realize that I won't be switching to Emacs that
day).

Thank you for taking the time to write all of this.

~~~
nonrecursive
Thank you for the feedback! Encouraging comments like this really help keep me
motivated. I'm glad that the emacs tutorial was useful for you :)

------
phren0logy
I have been really enjoying this tutorial. If you wanted to be super timely
you could add instructions for doing it in Light Table.

~~~
grayrest
Basic instructions. I use cmd for the shortcuts below, substitute ctrl on non-
mac platforms.

1\. Install Leiningen [http://leiningen.org/](http://leiningen.org/) you do
not need to install clojure, lein will grab clojure for you.

2\. `lein new playground` from the command line to create a 'playground'
project

3\. Open Light Table

4\. ctrl-space `woto` for "Toggle Workspace tree"

5\. Add the playground project folder you just created

6\. cmd-o `core.clj` to open the main clojure file for the project

7\. On an empty line type `(+ 1 1)` and hit cmd-enter

Things will grind away for a while as all the dependencies are downloaded and
the JVM starts up. Get a cup of coffee or something. Eventually you'll see a
green `2` show up.

You can then type anything in the tutorial and hit cmd-enter to evaluate it or
cmd-shift-enter to evaluate the entire file. Think of the file as a shell with
an editable history instead of something you'd want to commit to source
control.

Documentation is searchable via ctrl-shift-d or moving your cursor on top of a
function name and hitting ctrl-d. Autocomplete is available on tab, you can
jump to definition with cmd-. and back with cmd-,

~~~
dserban
Very useful!

Additional question: I noticed how on the clojurescreencasts site the author
of the videos uses InstaREPL in split screen mode. I couldn't figure out how
to do that with my own installation of LT. Do you know?

~~~
grayrest
The split is 'Tabset: Add a tabset' and you can just drag the instarepl tab
over.

------
actsasbuffoon
I love the pacing of this tutorial. It has a wonderful no-nonsense delivery,
and the pacing is fast enough to feel excitingly informative, but not so fast
as to be intimidating.

This is really great writing. As an Emacs user who hasn't yet gotten very far
into a lisp, I look forward to having time to sit down and really dig into
this tutorial.

Thanks for creating this!

------
tokipin
i found the Clojure koans useful.
([http://clojurekoans.com/](http://clojurekoans.com/)) they're aimed at
beginners so they would be a good companion/followup to this

~~~
elwell
this is a good read: [https://github.com/bbatsov/clojure-style-
guide](https://github.com/bbatsov/clojure-style-guide)

------
euphemize
hey great tutorial! really easy to go through, super helpful.

My only suggestion : it would be great to have a small
reference/cheatsheet/table to convert equivalent data structures and other
syntactic details from closure to other languages. I found myself scrolling
back up a lot to remember what "def" meant (coming from python this was
confusing), whether "vector" was a dict or a list, etc. It interrupted the
reading for a few seconds every time until "ah ha!" I found it.

I remember spending about 50% of my time learning Mongo syntax just checking
out their mysql <-> mongo syntax table - I assume most people checking out
your tutorial will have experience with some previous form of programming
(like me).

~~~
ryanatkn
cljs <-> js
[http://himera.herokuapp.com/synonym.html](http://himera.herokuapp.com/synonym.html)

~~~
masklinn
A bit outdated though e.g. for the first one, since 0.0.2060 cljs has grown
(enable-console-print!) which sets _print-fn_ to a wrapper around console.log.
As a result, one can use all the usual clojure printing functions[0] and the
output will be sent to the browser console.

[0]
[http://clojure.org/other_functions#Other%20Useful%20Function...](http://clojure.org/other_functions#Other%20Useful%20Functions%20and%20Macros-
Printing)

------
mattfenwick
As a Clojure fan, while I appreciate the author's effort, and admit I would do
a much worse job, I'm bothered by oversimplifications like these:

\- "Like all Lisps, it employs a uniform structure"

\- "All Clojure code is written in a uniform structure"

\- "Forms have a uniform structure."

\- "In other languages, different operations might have different structures
depending on the operator and the operands."

\- "No matter what operator you're using or what kind of data you're operating
on, the structure is the same."

It's pretty obvious that forms don't have a uniform structure (e.g. the
structure of a number is pretty different from the structure of a vector), and
that the structure depends on the operator (e.g. `def` special form vs. `or`
macro).

Yes, Clojure syntax is relatively simple, no need to oversell it.

Still, that's a minor issue that doesn't detract from the overall quality and
usefulness of the work.

~~~
nonrecursive
One of the ideas I'm trying to convey is that the structure of the code is
different from the syntax. With Clojure, special forms like def, if, etc,
provide syntax in that each one has different rules for how their arguments
get evaluated or, in the case of def, how the environment is changed. On top
of that, you have macros which allow you to introduce arbitrary syntax.

However, all Clojure code does have the same uniform structure. It's all
composed of s-expressions, which are either atoms or other s-expressions
enclosed in parentheses (for lists), braces (for maps), or brackets (for
vectors).

Thanks again for this feedback, having to explain this has given me some ideas
for how to improve the chapter :)

------
lgas
Technically this is the transliteration of that ruby code:

    
    
        (def severity :mild)
        (def error_message "OH GOD! IT'S A DISASTER! WE'RE ")
        (if (= severity :mild)
          (def error_message (str error_message "MILDLY INCONVENIENCED!"))
          (when (= severity :terrible)
            (def error_message (str error_message "DOOOOOOOMED!"))))
    

And if we consider that a good transliteration then I'm not sure why this
wouldn't suffice for the second one:

    
    
        (def failed_protagonist_names [
           "Larry Potter"
           "Doreen the Explorer"
           "The Incredible Bulk"
        ])
    
        (def failed_protagonist_names
            (assoc failed_protagonist_names 0 "Gary Potter"))
    
         ;; => ["Gary Potter" "Doreen the Explorer" "The Incredible Bulk"]

~~~
nonrecursive
This repl snippet should show that you're not actually changing a data
structure in place. Rather, you're creating a new data structure and changing
an existing binding:

    
    
      user=> (def a [1 2 3])
      user=> (def b a)
      user=> (def a ["a" "b" "c"])
      user=> a
      ["a" "b" "c"]
      user=> b
      [1 2 3]

------
bcarrell
This is really helpful. As someone who's never worked with a JVM language (or
Lisp, for that matter) or Emacs, braveclojure is really enjoyable. Thanks!

------
danielweber
I've been having fun using clojure over the past week or two, and it's really
nice to get a tutorial on all the vocabulary. Thanks.

