Concludes with:<p><i>By this point I highly recommend actually writing some code to solidify your Clojure knowledge if you haven't started already.</i><p>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.<p>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.<p>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.
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".
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 :)
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.<p>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.<p>Thanks for creating this!
i found the Clojure koans useful. (<a href="http://clojurekoans.com/" rel="nofollow">http://clojurekoans.com/</a>) they're aimed at beginners so they would be a good companion/followup to this
hey great tutorial! really easy to go through, super helpful.<p>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.<p>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).
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:<p>- "Like all Lisps, it employs a uniform structure"<p>- "All Clojure code is written in a uniform structure"<p>- "Forms have a uniform structure."<p>- "In other languages, different operations might have different structures depending on the operator and the operands."<p>- "No matter what operator you're using or what kind of data you're operating on, the structure is the same."<p>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).<p>Yes, Clojure syntax is relatively simple, no need to oversell it.<p>Still, that's a minor issue that doesn't detract from the overall quality and usefulness of the work.
Technically this is the transliteration of that ruby code:<p><pre><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!"))))
</code></pre>
And if we consider that a good transliteration then I'm not sure why this wouldn't suffice for the second one:<p><pre><code> (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"]</code></pre>
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!